我正在使用C ++开发一个处理逗号分隔数据(CSV)的项目。我所做的是将.csv文件中的数据读入CsvRow对象的向量中 所以,今天我遇到了一个非常奇怪的std :: bad_alloc异常被抛出更奇怪的情况。也就是说,在我得到异常抛出之前,我设法获得更多时间的第一个测试用例是将整个csv文件读入向量。该文件包含500,000行,大小约为70MB。该文件像魅力一样被读入内存,但是在进入排序过程几秒钟后,std :: bad_alloc被抛出。它使用了大约67MB的RAM 注意:我正在使用boost的flyweights以减少内存消耗。
但是,这个测试用例甚至更奇怪: 我正在读一个带有几百行的146KB文件,这次我在将数据读入一个向量时遇到异常,这在以前成功读取70MB是完全荒谬的。
我怀疑内存泄漏,但我的机器有8GB内存,使用64位Windows 8。 我正在使用CodeBlocks和MinGW 64位增强版。 任何帮助,将不胜感激。 下面是一段代码,其中抛出了std :: bad_alloc:
从csv文件中读取数据
std::ifstream file(file_name_);
int k=0;
for (CsvIterator it(file); it != CsvIterator(); ++it) {
if(columns_ == 0) {
columns_ = (*it).size();
for (unsigned int i=0; i<columns_; i++) {
distinct_values_.push_back(*new __gnu_cxx::hash_set<std::string,
std::hash<std::string> >());
}
}
for (unsigned int i=0; i<columns_; i++) {
distinct_values_[i].insert((*it)[i]);
}
all_rows_[k]=(*it);
k++;
}
使用存储在我的类
中的内部结构对矢量进行排序struct SortRowsStruct
{
CsvSorter* r;
SortRowsStruct(CsvSorter* rr) : r(rr) { };
bool operator() (CsvRow a, CsvRow b)
{
for (unsigned int i=0; i<a.size(); i++) {
if(a[r->sorting_order_[i]] != b[r->sorting_order_[i]]) {
int dir = r->sorting_direction_[i];
switch(dir) {
case 0:
return (a[r->sorting_order_[i]] < b[r->sorting_order_[i]]);
break;
case 1:
return !(a[r->sorting_order_[i]] < b[r- >sorting_order_[i]]);
break;
case 2:
return true;
break;
default:
return true;
}
}
}
return true;
}
};
然后,我正在使用std::sort()
对CsvRows的矢量进行排序
SortRowsStruct s(this);
std::sort(all_rows_.begin(), all_rows_.end(), s);
这一行看起来很可疑,但我无法找到一种更简单的方法来初始化这些哈希集。
distinct_values_.push_back( *new __gnu_cxx::hash_set<std::string,
std::hash<std::string> >() );
在析构函数中删除这些哈希集会导致程序崩溃(SIGSEGV) 哦,另外要指出的是,由于我的MinGW是64位,我不能使用默认的32位gdb调试器。 32位gdb被窃听,不适用于MinGW 64。
修改:
我在CsvRow类中使用的 boost::flyweight<std::string>
会导致问题吗?
除此之外,这是CsvRow
类的一部分:
private:
std::vector<boost::flyweights::flyweight<std::string> > row_data_;
[]
类上的重载CsvRow
运算符:
std::string const& CsvRow::operator[](std::size_t index) const
{
boost::flyweights::flyweight<std::string> fly = row_data_[index];
return fly.get();
}
提前致谢
编辑 - 已解决:
所以,这个问题解决了我的问题,虽然我甚至没有想到它。
我们传递给std::sort()
的每个自定义比较器必须是严格的弱排序,即:
1。漫反射
2.不对称
3.传递性
4.不可比性的传递性
更多信息:This question和This Wiki article
实际上,我没有遵循第一个(反射性),也就是说,如果两个CsvRow
对象都相等,它不应该“比较”它们并返回true
,就像它们没问题一样,但是而是返回false
。
我通过仅在CsvRow a
和CsvRow b
相等时更改默认返回值来解决整个问题。
bool operator() (CsvRow a, CsvRow b)
{
for (unsigned int i=0; i<a.size(); i++) {
if(a[r->sorting_order_[i]] != b[r->sorting_order_[i]]) {
...
...
}
}
return false; //this line does not violate the irreflexivity rule
//return true; //but this one does
}
感谢所有试图提供帮助的人。 如果遇到类似问题,请记住此解决方案。这很棘手。
答案 0 :(得分:1)
此:
distinct_values_.push_back( *new __gnu_cxx::hash_set<std::string,
std::hash<std::string> >() );
看起来您正在尝试向向量添加一个默认构造的元素。有一种更简单的方法:
distinct_values_.resize(distinct_values_.size() + 1);
除了更容易键入和更通用之外,它也更正确:我们不应该在这里new
任何东西,只是在最后创建一个值,我们应该让矢量构造而不是复制它,这可能是浪费。
当然,我们绝不应该尝试delete
这些价值观。