gpt4 book ai didi

C++ 使用 std::sort 为非常小的 std::vector 抛出 std::bad_alloc 异常

转载 作者:行者123 更新时间:2023-11-28 07:15:32 35 4
gpt4 key购买 nike

我正在用 C++ 开发一个处理逗号分隔数据 (CSV) 的项目。我所做的是将数据从 .csv 文件读取到 CsvRow 对象的 vector 中。
所以,今天我遇到了一个非常奇怪的 std::bad_alloc 异常,在更奇怪的情况下被抛出。即,在抛出异常之前我设法获得更多时间的第一个测试用例是将整个 csv 文件读入 vector 。该文件包含 500,000 行,大小约为 70MB。该文件像魅力一样被读入内存,但在排序过程几秒钟后,std::bad_alloc 被抛出。它使用了大约 67MB 的 RAM注意:我正在使用 boost 的 flyweights 以减少内存消耗。

但是,这个测试用例更奇怪:我正在读取一个包含数百行的 146KB 文件,这次我在将数据读入 vector 时遇到异常,这在之前成功读取 70MB 时是完全荒谬的。

我怀疑内存泄漏,但我的机器有 8GB RAM,使用 64 位 Windows 8。我正在使用 CodeBlocks 和 MinGW 64 位 boost 发行版。任何帮助,将不胜感激。这是抛出 std::bad_alloc 的代码块:

  1. 从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++;
    }
  2. 使用存储在我的类中的内部结构对 vector 进行排序

    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 的 vector 进行排序

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 上的运算符(operator)类:

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 questionThis Wiki article
其实我并没有按照第一个(irreflexivity),也就是说,如果两个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
}

感谢所有试图提供帮助的人。请记住此解决方案,以防您遇到类似问题。这非常棘手。

最佳答案

这个:

distinct_values_.push_back( *new __gnu_cxx::hash_set<std::string,                                     
std::hash<std::string> >() );

看起来您正在尝试向 vector 中添加一个默认构造的元素。有一个更简单的方法:

distinct_values_.resize(distinct_values_.size() + 1);

除了更容易输入、更通用之外,它也更正确:我们不应该new这里的任何东西,只是在最后创建一个单一的值,我们应该让vector 构造它而不是复制它,这可能是浪费。

当然,我们永远不应该尝试删除这些值。

关于C++ 使用 std::sort 为非常小的 std::vector 抛出 std::bad_alloc 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20295680/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com