"std :: bad_alloc": я использую слишком много памяти? - PullRequest
11 голосов
/ 05 декабря 2011

Сообщение:

terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc

Я посмотрел на трассировку GDB, и это метод самого низкого уровня, который я реализовал сам:

/*
 * get an array of vec3s, which will be used for rendering the image
 */
vec3 *MarchingCubes::getVertexNormalArray(){
    // Used the same array size technique as getVertexArray: we want indices to match     up
    vec3 *array = new vec3[this->meshPoints.getNumFaces() * 3]; //3 vertices per face

    int j=0;
    for (unsigned int i=0; i < (this->meshPoints.getNumFaces() * 3); i++) {
        realVec normal = this->meshPoints.getNormalForVertex(i);
 //     PCReal* iter = normal.begin();

        if (normal.size() >= 3) {
            array[j++] = vec3(normal[0], normal[1], normal[2]);
        }
        cout << i << " ";
    }

    return array;
}

Выражение cout, которое вы видите выше, указывает, что оно завершается после 7000+ итераций. Вышеуказанная функция вызывается только один раз в конце моего приложения. Я вызываю очень похожую функцию перед вызовом выше, это не вызывает проблем.

Ответы [ 3 ]

22 голосов
/ 05 декабря 2011

(перемещение / расширение по комментариям)

Поскольку вы выделяете новый массив каждый раз, не освобождая его, у вас огромная утечка памяти, то есть вы продолжаете запрашивать память в системе, даже не давая ееназад.В конце концов пространство в куче заканчивается, и при следующем выделении все, что вы получите, это исключение std::bad_alloc.

Решение в стиле «С» будет заключаться в том, чтобы помнить об освобождении такой памяти, когда вам не нужноэто больше (с delete[]), но это (1) подвержено ошибкам (например, если у вас есть несколько путей возврата внутри функции) и (2) потенциально небезопасно для исключения (каждая инструкция становится потенциальным путем возврата, если выесть исключения!).Таким образом, этого следует избегать.

Идиоматическое решение C ++ заключается в использовании либо интеллектуальных указателей - небольших объектов, которые инкапсулируют указатель и освобождают связанную память при их уничтожении, либо стандартных контейнеров, которые делают более или менее то же самое, но с семантикой копирования и некоторыми дополнительными функциями (включая сохранение размера массива внутри них).

4 голосов
/ 02 марта 2018

Я получил эту ошибку при попытке выделить массив отрицательной длины:

double myArray = new double [-9000];

На всякий случай, если это кому-нибудь поможет.

3 голосов
/ 06 декабря 2011

Моя проблема оказалась в том, что this->meshPoints.getNormalForVertex(i) обращается к массиву (или к вектору, я не помню), длина которого меньше this->meshPoints.getNumFaces() * 3. Так что доступ был за пределами.

...