[英]std::vector::resize results in a crash in a template class
Here's the code : The place where it crashed is marked with a comment( //////crash
). 这是代码:崩溃的地方标有comment(
//////crash
)。 I don't know what results in the problem. 我不知道是什么导致了问题。
After I print the size of data got from file,It shows ' 1 ' means that the array should only contains 1 element. 在我打印了从文件中获得的数据大小后,它显示为“ 1 ”表示该数组应只包含1个元素。 So it seems that there's no 'bad_allocate error' ... Could you guys help me ?
看来没有“ bad_allocate错误”……你们能帮我吗? I would appreciate your kindly help very much.
非常感谢您的帮助。 :)
:)
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<string.h>
#include<type_traits>
using namespace std;
bool read_int(int& val,FILE*& fp)
{
if(fp == nullptr)
return false;
fread(&val,sizeof(int),1,fp);
return true;
}
bool write_int(int val,FILE*& fp)
{
if(fp == nullptr)
{
return false;
}
fwrite(&val,sizeof(int),1,fp);
return true;
}
struct SANOBJ
{
char path[128];
char nickname[40];
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
if(_p == nullptr || _n == nullptr)
*this = {};
int m = strlen(_p),n = strlen(_n);
if(m < 128) strcpy(path,_p);
if(n < 40) strcpy(nickname,_n);
}
~SANOBJ(){}
SANOBJ(const SANOBJ& other)
{
memcpy(path,other.path,sizeof(char) * 128);
memcpy(nickname,other.nickname,sizeof(char) * 40);
}
bool operator < (const SANOBJ& other) const
{
return string(path) < string(other.path);
}
bool operator == (const SANOBJ& other) const
{
return (strcmp(other.path,path) == 0);
}
};
template <typename source_type> //the 'source_type' type need to have the member 'int m_index'
class FrameQueue
{
public:
FrameQueue() //fill the 1st frame automatically
{
source_type new_node;
new_node.m_index = 0;
m_data.push_back(new_node);
}
FrameQueue(const FrameQueue& other)
{
m_data = other.m_data;
}
bool AddFrame(const source_type& other) // keeps an ascending order
{
int index = _binary_search(other);
if(index != -1)
{
return false;
}
m_data.insert(std::upper_bound(m_data.begin(),m_data.end(),other,
[](const source_type& a,const source_type& b)->bool const{return a.m_index < b.m_index;}
),other);
return true;
}
bool DeleteFrameByElemIndex(int elemIndex) //delete frame according to the index of frame in the queue
{
if(elemIndex < 0)
return false;
if(elemIndex >= m_data.size())
return false;
typename std::vector<source_type>::iterator it ;
it = m_data.begin() + elemIndex;
it = m_data.erase(it);
return true;
}
bool DeleteFrameByFrameIndex(int frameIndex)
{
source_type node = {};
node.m_index = frameIndex;
int index = _binary_search(node);
if(index == -1)
{
return false;
}
typename std::vector<source_type>::iterator it;
it = m_data.begin() + index;
it = m_data.erase(it);
return true;
}
bool Clear() // There would always be a single frame
{
source_type new_node = {};
new_node.m_index = 0;
m_data.clear();
m_data.push_back(new_node);
return true;
}
bool WriteFile(FILE*& fp)
{
if(fp == nullptr)
return false;
bool result = write_int(m_data.size(),fp);
if(result == false)
return false;
fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
return true;
}
bool ReadFile(FILE*& fp)
{
if(fp == nullptr)
return false;
int data_size;
bool result = read_int(data_size,fp);
if(result == false)
return false;
if(data_size > 0)
{
m_data.resize(data_size);
fread(&(m_data[0]),sizeof(source_type),data_size,fp);
}
return true;
}
private:
int _binary_search(source_type target)
{
int l = 0,r = (int)m_data.size() - 1,mid;
while(l<=r)
{
mid = (l + r) / 2;
if(m_data[l].m_index == target.m_index)
{
return l;
}
if(m_data[r].m_index == target.m_index)
{
return r;
}
if(m_data[mid].m_index == target.m_index)
{
return mid;
}
if(m_data[mid].m_index > target.m_index)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
public:
vector<source_type> m_data;
};
template<typename source_type>
class UniqueSource
{
public:
UniqueSource(){}
~UniqueSource(){}
bool Add(const source_type& other)//return false when insert failed,otherwise return true
{
if(m_map_source_to_index.find(other) == m_map_source_to_index.end())
{
int map_size = m_map_source_to_index.size();
m_data.push_back(other);
m_map_source_to_index.insert(pair<source_type,int>(other,map_size));
m_result.push_back(map_size);
return true;
}
else
{
m_result.push_back(m_map_source_to_index[other]);
return true;
}
return false;
}
bool Delete(int elemIndex) // delete the elem by elem Index,If succeed ,return true,otherwise return false
{
if(elemIndex < 0)
return false;
if(elemIndex >= m_data.size())
return false;
typename std::map<source_type,int>::iterator mit;
typename std::vector<source_type>::iterator vit;
for(mit = m_map_source_to_index.begin();mit!=m_map_source_to_index.end();++mit)
{
m_map_source_to_index.erase(mit);
}
vit = m_data.begin() + elemIndex;
m_data.erase(vit);
return true;
}
bool Clear()
{
m_map_source_to_index.clear();
m_data.clear();
m_result.clear();
return true;
}
bool WriteFile(FILE*& fp)
{
if(fp == nullptr)
return false;
bool result = write_int(m_data.size(),fp);
if(result == false)
return false;
if(m_data.size() > 0)
fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
result = write_int(m_result.size(),fp);
if(result == false)
return false;
if(m_result.size() > 0)
fwrite(&(m_result[0]),sizeof(int),m_result.size(),fp);
return true;
}
bool ReadFile(FILE*& fp)
{
if(fp == nullptr)
return false;
Clear();
int data_size;
read_int(data_size,fp);
if(data_size > 0)
{
printf("[%d]",data_size);
m_data.resize(data_size); /////////////////Crash!!!!!!!!!!!!
printf("Resize Ok\r\n");
fread(&(m_data[0]),sizeof(source_type),data_size,fp);
}
read_int(data_size,fp);
printf("[%d]",data_size);
if(data_size > 0)
{
m_result.resize(data_size);
fread(&(m_result[0]),sizeof(int),data_size,fp);
}
return true;
}
//private:
map<source_type,int> m_map_source_to_index;
vector<source_type> m_data;
vector<int> m_result; //the index I want
};
int main()
{
UniqueSource<SANOBJ> m;
SANOBJ t = {"123","456"};
m.Add(t);
printf("Added\r\n");
FILE* fp = nullptr;
fp = fopen("test.b","wb");
if(fp == nullptr)
{
printf("Failed...\r\n");
}
bool ret = false;
ret = m.WriteFile(fp);
if(ret)
{
printf("Writed!\r\n");
fclose(fp);
}
fp = fopen("test.b","rb");
if(fp == nullptr)
{
printf("Failed...\r\n");
}
ret = m.ReadFile(fp);
fclose(fp);
printf("Readed\r\n");
for(int i=0;i<m.m_data.size();i++)
printf("%s %s\r\n",m.m_data[i].path,m.m_data[i].nickname);
return 0;
}
Yes. 是。 The problem is is with *this = {}
问题在于* this = {}
If I were you, I'd rewrite SANOBJ constructor like this (this is a rough code and you may need to slightly modify it if you wish) 如果您是我,我将像这样重写SANOBJ构造函数(这是一个粗略的代码,如果需要,您可能需要稍作修改)
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
if (( _p != nullptr ) && ((strlen(_p) < 128)))
strcpy(path,_p);
if (( _n != nullptr ) && ((strlen(_n) < 40)))
strcpy(nickname,_n);
}
It'll resolve the problem. 它将解决问题。
Naturally, I don't play with *this (not this). 自然,我不玩* this(不是this)。
*this = {}
default-constructs a new SANOBJ
instance and then assigns it to *this
. *this = {}
默认构造一个新的SANOBJ
实例,然后将其分配给*this
。 This would normally be OK, but here you are calling it from the SANOBJ
default constructor (making the logic being something like "to default-construct a SANOBJ
, default-construct a SANOBJ
and then assign its value to myself"), leading to infinite recursion and eventually a stack overflow. 通常这是可以的,但是在这里您要从
SANOBJ
默认构造函数调用它(使逻辑类似于“默认构造SANOBJ
,默认构造SANOBJ
,然后将其值分配给我自己”),导致无限递归并最终导致堆栈溢出。
Sidenote: The copy constructor is not needed. 旁注:不需要复制构造函数。
If you want to be sure that the member variables are empty (char path[128] and char nickname[40]) set at the beginning of the constructor something like: path[0] = '\\0'; nickname[0] = '\\0';
如果要确保成员变量为空(char path [128]和char昵称[40]),请在构造函数的开头设置以下内容:
path[0] = '\\0'; nickname[0] = '\\0';
path[0] = '\\0'; nickname[0] = '\\0';
Or use something like on constructor: 或者在构造函数上使用类似的东西:
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
: path(), nickname()
{
}
But don't use *this= {}
但不要使用
*this= {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.