Eliminación de C++: ¿elimina mis objetos pero aún puedo acceder a los datos?

Resuelto Ash asked hace 15 años • 13 respuestas

He escrito un juego de tetris sencillo y funcional en el que cada bloque es una instancia de un bloque único de clase.

class SingleBlock
{
    public:
    SingleBlock(int, int);
    ~SingleBlock();

    int x;
    int y;
    SingleBlock *next;
};

class MultiBlock
{
    public:
    MultiBlock(int, int);

    SingleBlock *c, *d, *e, *f;
};

SingleBlock::SingleBlock(int a, int b)
{
    x = a;
    y = b;
}

SingleBlock::~SingleBlock()
{
    x = 222;
}

MultiBlock::MultiBlock(int a, int b)
{
    c = new SingleBlock (a,b);
    d = c->next = new SingleBlock (a+10,b);
    e = d->next = new SingleBlock (a+20,b);
    f = e->next = new SingleBlock (a+30,b);
}

Tengo una función que busca una línea completa y recorre la lista vinculada de bloques eliminando los relevantes y reasignando los punteros ->siguiente.

SingleBlock *deleteBlock;
SingleBlock *tempBlock;

tempBlock = deleteBlock->next;
delete deleteBlock;

El juego funciona, los bloques se eliminan correctamente y todo funciona como debería. Sin embargo, tras la inspección, todavía puedo acceder a bits aleatorios de datos eliminados.

Si imprimo cada uno de los valores "x" de los bloques individuales eliminados DESPUÉS de su eliminación, algunos de ellos devuelven basura aleatoria (confirmando la eliminación) y otros devuelven 222, lo que me indica que, aunque se llamó al destructor, los datos en realidad no se eliminaron. el montón. Muchas pruebas idénticas muestran que siempre son los mismos bloques específicos los que no se eliminan correctamente.

Los resultados:

Existing Blocks:
Block: 00E927A8
Block: 00E94290
Block: 00E942B0
Block: 00E942D0
Block: 00E942F0
Block: 00E94500
Block: 00E94520
Block: 00E94540
Block: 00E94560
Block: 00E945B0
Block: 00E945D0
Block: 00E945F0
Block: 00E94610
Block: 00E94660
Block: 00E94680
Block: 00E946A0

Deleting Blocks:
Deleting ... 00E942B0, X = 15288000
Deleting ... 00E942D0, X = 15286960
Deleting ... 00E94520, X = 15286992
Deleting ... 00E94540, X = 15270296
Deleting ... 00E94560, X = 222
Deleting ... 00E945D0, X = 15270296
Deleting ... 00E945F0, X = 222
Deleting ... 00E94610, X = 222
Deleting ... 00E94660, X = 15270296
Deleting ... 00E94680, X = 222

¿Se espera poder acceder a datos del más allá?

Lo siento si esto es un poco largo.

Ash avatar Dec 19 '09 03:12 Ash
Aceptado

¿Se espera poder acceder a datos del más allá?

Esto se conoce técnicamente como comportamiento indefinido . No te sorprendas si tampoco te ofrece una lata de cerveza.

dirkgently avatar Dec 18 '2009 20:12 dirkgently

¿Se espera poder acceder a datos del más allá?

En la mayoría de los casos, sí. Llamar a eliminar no pone a cero la memoria.

Tenga en cuenta que el comportamiento no está definido. Al utilizar ciertos compiladores, es posible que la memoria se ponga a cero. Cuando llamas a eliminar, lo que sucede es que la memoria se marca como disponible, por lo que la próxima vez que alguien haga algo nuevo , la memoria podrá usarse.

Si lo piensas bien, es lógico: cuando le dices al compilador que ya no estás interesado en la memoria (usando eliminar ), ¿por qué la computadora debería dedicar tiempo a ponerla a cero?

Martin avatar Dec 18 '2009 20:12 Martin

Eliminar no elimina nada, simplemente marca la memoria como "libre para su reutilización". Hasta que alguna otra llamada de asignación reserve y llene ese espacio, tendrá los datos antiguos. Sin embargo, confiar en eso es un gran no-no, básicamente, si eliminas algo, olvídalo.

Una de las prácticas a este respecto que se encuentra a menudo en las bibliotecas es la función Eliminar:

template< class T > void Delete( T*& pointer )
{
    delete pointer;
    pointer = NULL;
}

Esto evita que accedamos accidentalmente a una memoria no válida.

Tenga en cuenta que está perfectamente bien llamar delete NULL;.

Kornel Kisielewicz avatar Dec 18 '2009 20:12 Kornel Kisielewicz

Es lo que C++ llama comportamiento indefinido: es posible que puedas acceder a los datos, o puede que no. En cualquier caso, no es lo correcto.

 avatar Dec 18 '2009 20:12