我正在处理一个处理逗号分隔数据 (CSV) 的 C++ 项目。我所做的是将 .csv 文件中的数据读取到 CsvRow 对象的向量中。
所以,今天我遇到了一个非常奇怪的 std::bad_alloc 异常,它在更奇怪的情况下被抛出。即,我设法获得更多时间直到引发异常的第一个测试用例是将整个 csv 文件读入向量。该文件由 500,000 行组成,大小约为 70MB。该文件像魅力一样被读入内存,但在排序过程几秒钟后,std::bad_alloc 被抛出。它使用了大约 67MB 的 RAM 注意:我正在使用 boost 的 flyweights 以减少内存消耗。
但是,这个测试用例更奇怪:我正在读取一个有几百行的 146KB 文件,这次我在将数据读入向量时遇到了异常,这完全是荒谬的,之前成功读取了 70MB。
我怀疑内存泄漏,但我的机器有 8GB 的 RAM,使用 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 一起使用。
编辑:
我 boost::flyweight<std::string>
在 CsvRow 类中使用的会导致问题吗?
除此之外,这是该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 and 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
}
感谢所有试图提供帮助的人。请记住此解决方案,以防您遇到类似问题。这很棘手。