сортировка — C ++ вызывает исключение std :: bad_alloc для очень маленького std :: vector с использованием std :: sort

Я работаю над проектом на C ++, который имеет дело с данными, разделенными запятыми (CSV). Что я делаю, так это чтение данных из файла .csv в вектор объектов CsvRow.
Итак, сегодня я столкнулся с действительно странными исключениями std :: bad_alloc, возникающими в гораздо более странных ситуациях. А именно, первым тестовым примером, в котором мне удалось получить немного больше времени, пока я не сгенерировал исключение, было чтение целого файла csv в вектор. Файл состоит из 500 000 строк, а его размер составляет около 70 МБ. Файл считывался в память, как талисман, но затем, через несколько секунд после процедуры сортировки, выдается std :: bad_alloc. Он использовал примерно 67 МБ оперативной памяти
Примечание: я использую маховики boost для уменьшения потребления памяти.

НО, этот тест был еще более странным:
Я читаю файл размером 146 КБ с несколькими сотнями строк, и на этот раз я получил исключение при чтении данных в вектор, что совершенно нелепо, если ранее было успешно прочитано 70 МБ.

Я подозреваю утечку памяти, но моя машина имеет 8 ГБ оперативной памяти, используя 64-разрядную версию Windows 8.
Я использую CodeBlocks и дистрибутив с 64-битным бустом MinGW.
Любая помощь будет оценена.
Вот фрагмент кода, в который выбрасывается 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. Сортировка вектора с использованием внутренней структуры, хранящейся в моем классе

    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)
Да, и еще одна вещь, на которую следует обратить внимание, это то, что я не могу использовать стандартный 32-битный отладчик GDB из-за того, что мой MinGW 64-битный. 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. Транзитивность несопоставимости

Больше информации на:Этот вопрос а также Эта статья в вики
На самом деле, я не следовал за первым (нерефлексивность), то есть, если оба 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

Решение

Это:

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

Похоже, вы пытаетесь добавить один созданный по умолчанию элемент к вектору. Есть более простой способ:

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

Помимо того, что легче набирать текст и быть более общим, оно также намного правильнее: мы не должны newчто-то здесь, просто создаем одно значение в конце, и мы должны позволить вектору создать его, а не копировать в него, что может быть расточительным.

И, конечно, мы никогда не должны пытаться delete эти значения.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector