2011-03-04 14 views
5

que tengo una clase Foo para el que he sobrecargado el operador + de la siguiente manera:una copia con los operadores sobrecargados

Foo Foo::operator+(const Bar &b) 
{ 
    Foo copy = (*this); 
    if (someCondition) return copy; 
    //snip 
} 

Para mí, esto parece razonable. Sin embargo, cada vez que devuelvo copia, Visual Studio me alerta de un error que 'puede deberse a una corrupción del montón'. ¿Hay algo mal con lo que hice?

editar: actualizando con más información.

El mensaje de error:

Windows ha desencadenado un punto de interrupción en sample.exe.

Esto puede ser debido a una corrupción de la montón, lo que indica un error en sample.exe o cualquiera de los DLL se ha cargados.

Esto también puede ser debido a la presión F12 usuario mientras sample.exe tiene enfoque.

La ventana de salida puede tener más información de diagnóstico .

El constructor de copia:

Foo::Foo(const Foo&p) 
{ 
    some_pointer = p.get_some_pointer(); 
    some_value = p.get_some_value(); 
} 

El código se rompe a:

//within dbgheap.c 
    extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
      const void * pUserData 
      ) 
    { 
      if (!pUserData) 
       return FALSE; 

      if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE)) 
       return FALSE; 

      return HeapValidate(_crtheap, 0, pHdr(pUserData)); 
    } 
+4

¿Puede mostrarnos el constructor de copia de 'Foo'? –

+1

¿Cuál es el código de error? – metdos

+0

@ Space_C0wb0y @metdos He actualizado con más información – socks

Respuesta

3

Ese tipo de error se asocia generalmente con múltiples deleciones (o libre) de la mismo puntero, o con algunas situaciones más oscuras (adquiriendo de un montón y lanzando a un montón diferente, pero que probablemente no es el caso aquí)

Lo primero que haría es mirar los destructores y comprobar que no se trata de copia poco profunda y eliminación doble. Por ejemplo con el siguiente código:

// buggy!!! 
struct test { 
    int * data; 
    test() : data(new int[5]) {} 
    ~test() { delete [] data; } 
    test(test const & rhs) : data(rhs.data) {} 
    test& operator=(test const & rhs) { 
     data = rhs.data; 
    } 
}; 
int main() { 
    test t1;   // 5 ints allocated int t1.data 
    test t2(t1); // no memory allocated, t2.data == t1.data 
} // t2 out of scope: t2.~test() => delete t2.data 
    // t1 out of scope: t1.~test() => delete t1.data but both are the same: double delete 

Si este es el caso, usted puede decidir si desea tener copias de poca profundidad o hacer copias de profundidad. En el segundo caso, el constructor de copias (y el operador de asignación) deben asignar su propia memoria, mientras que en el segundo caso debe asegurarse de que la memoria no se libere dos veces.

Como siempre con los punteros, es mejor delegar la gestión de recursos en clases externas (preconstruidas). En el caso de propiedad exclusiva (y copias en profundidad), probablemente debería usar std::auto_ptr (o std::unique_ptr en C++ 0x - o las variantes de impulso). En el segundo caso, usar boost::shared_ptr (o std::shared_ptr en C++ 0x) garantizará que los datos se compartan y solo se eliminen una vez.

+1

Y si la clase no posee el objeto al que apunta el puntero, prefiera una referencia. –

+1

@Space: una preferencia que efectivamente hará que la clase no sea asignable (lo que quizás sería extraño para una clase con operadores aritméticos) ... – visitor

+0

@visitor: Correcto, no lo consideré. –

Cuestiones relacionadas