2012-07-26 10 views
5

Tengo el siguiente código y no estoy seguro de por qué recibo el error de corrupción detectado en el montón cuando golpea el destructor de Myclass. Creo que estoy desasignando la memoria correctamente?Se detectó corrupción en el montón después del bloque normal

#include <iostream> 
#include <vector> 
using namespace std; 

class MyClass{ 
private: 
    char* mp_str; 
public: 
    MyClass():mp_str(NULL){} 
    ~MyClass(){ 
     delete [] mp_str; 
    } 

    void setString(const char* str); 
    void printString(); 
}; 

int main(){ 
    MyClass* a = new MyClass(); 
    std::vector<MyClass> myVector; 

    myVector.push_back(*a); 

    a->setString("Hello World"); 
    myVector[0].setString("Goodbye world"); 

    a->printString(); 
    myVector[0].printString(); 

    return 1; 
} 

void MyClass::setString(const char* const str){ 
    if(!str) 
     return; 

    size_t len = strlen(str); 

    if(!this->mp_str){ 
     this->mp_str = new char[len]; 
     memset(mp_str, 0, len+1); 
    } 
    strncpy(mp_str, str, len); 
} 

void MyClass::printString(){ 
    if(this->mp_str) 
     cout << mp_str; 
    else 
     cout << "No string found"; 
} 

EDITAR: (Código fijo)

void MyClass::setString(const char* const str){ 
    if(!str) 
     return; 

    size_t len = strlen(str); 

    if(!this->mp_str){ 
     this->mp_str = new char[len+1]; 
     memset(mp_str, 0, len+1); 
    } 
    strncpy(mp_str, str, len); 
} 

en main(), también añadió

delete a; 

antes de llamar retorno 1;

+5

necesitan la [regla de tres] (http://stackoverflow.com/questions/4172722/what- is-the-rule-of-three). – jxh

+3

también se filtra el objeto en 'a' –

+0

@yurikilochek: de acuerdo. arregló eso. – brainydexter

Respuesta

8

Debe asignar la longitud de la cadena +1, para tener en cuenta el nulo. Lo estás haciendo bien.

if(!this->mp_str){ 
    this->mp_str = new char[len+1]; 
    memset(mp_str, 0, len+1); 
} 
+0

¡Estoy de acuerdo con @Rafael! Suspiro, no vi este :( – brainydexter

+0

@brainydexter Presta atención, aunque este no es el único error. Ver comentarios arriba (que realmente deberían ser respuestas) –

+0

@KonradRudolph De acuerdo. – brainydexter

1

(Publicado después de la respuesta de Rafael fue aceptada, como debe ser.)

La saturación del búfer fue sin duda la causa raíz de este accidente en particular, pero el accidente podría haberse evitado mediante la simplificación de la mientras que la ejecución ajustando para la adherencia al Rule of Three. A saber, desde que implementó un destructor (para tratar con mp_str), también debería haber implementado un constructor de copia y un operador de asignación.

Pero, otra forma de adherirse a TRoT es evitar la necesidad de implementar cualquiera de esas cosas en absoluto. En este caso, el uso de un std::string en lugar de un char * habría resuelto tanto el accidente y ser compatible con Trot:

class MyClass{ 
private: 
    std::string mp_str; 
public: 
    void setString(const char* str) { mp_str = str ? str : ""; } 
    void printString() { 
     if (mp_str.size()) std::cout << mp_str; 
     else std::cout << "(mp_str is empty)"; 
    } 
}; 
+0

Sí y yo (re) leído ese enlace a TROT que publicaste. No había practicado la diversión con un puntero desde hace un tiempo, así que pensé en darle un giro a estas cosas otra vez. Usar clases como la cadena realmente te hace la vida más fácil. – brainydexter

+0

Aunque a veces tienes que escribir en bruto C! –

+0

@BrianReinhold: un puntero inteligente sería preferible a los punteros sin procesar, y aún permitirá que el código permanezca compatible con RoT. – jxh

Cuestiones relacionadas