ti-enxame.com

"std :: bad_alloc": estou usando muita memória?

A mensagem:

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

Eu olhei para o backtrace do gdb e este é o método de nível mais baixo que implementei:

/*
 * 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;
}

A declaração de cout que você vê acima indica que ela termina após 7000+ iterações. A função acima é chamada apenas uma vez perto do final do meu aplicativo. Eu chamo uma função muito semelhante antes de chamar o acima, isso não causa problemas.

10
Rooster

Meu problema acabou por ser que this->meshPoints.getNormalForVertex(i) acessa uma matriz (ou vetor, não me lembro) cujo comprimento é menor que this->meshPoints.getNumFaces() * 3. Então, estava acessando fora dos limites.

3
Rooster

(movendo/expandindo dos comentários)

Como você está alocando um novo array a cada vez sem desalocá-lo, você tem um grande vazamento de memória, ou seja, você continua pedindo memória ao sistema sem nunca devolvê-lo. Eventualmente, o espaço no heap é concluído e, na próxima alocação, tudo que você obtém é uma exceção std::bad_alloc.

A solução "C-style" seria lembrar de desalocar tal memória quando você não precisa mais dela (com delete[]), mas, isso é (1) propenso a erros (pense, por exemplo, se você tem múltiplos caminhos de retorno dentro de uma função ) e (2) potencialmente inseguro-inseguro (cada instrução se torna um caminho de retorno potencial se você tiver exceções!). Assim, esse caminho deve ser evitado.

A solução C++ idiomática é usar ponteiros inteligentes - objetos pequenos que encapsulam o ponteiro e desalocam a memória associada quando eles são destruídos - ou contêineres padrão, que fazem mais ou menos a mesma coisa, mas com semântica de cópia e um pouco mais sinos e assobios (incluindo o armazenamento do tamanho do array dentro deles).

21
Matteo Italia

Eu recebi este erro tentando alocar uma matriz de comprimento negativo:

double myArray = novo duplo [-9000];

Apenas no caso de ajudar alguém. 

2
Tim Mottram