C ++ delete - удаляет мои объекты, но я все еще могу получить доступ к данным? - PullRequest
29 голосов
/ 18 декабря 2009

Я написал простую, работающую игру в тетрис с каждым блоком в качестве экземпляра класса SingleBlock.

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);
}

У меня есть функция, которая просматривает полную строку и просматривает связанный список блоков, удаляя соответствующие и переназначая -> следующие указатели.

SingleBlock *deleteBlock;
SingleBlock *tempBlock;

tempBlock = deleteBlock->next;
delete deleteBlock;

Игра работает, блоки удаляются корректно, и все работает как положено. Однако при проверке я все еще могу получить доступ к случайным битам удаленных данных.

Если я печатаю каждое из удаленных значений «x» одного блока после их удаления, некоторые из них возвращают случайный мусор (подтверждая удаление), а некоторые возвращают 222, сообщая мне, что деструктор был назван данными на самом деле удаляется из кучи. Многие идентичные испытания показывают, что это всегда одни и те же конкретные блоки, которые не удаляются должным образом.

Результаты:

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

Может ли быть доступ к данным за пределами ожидаемой могилы?

Извините, если это немного затянуто.

Ответы [ 13 ]

0 голосов
/ 18 декабря 2009

Это приведет к неопределенному поведению и удалит освобождение памяти, но не приведет к ее повторной инициализации с нуля.

Если вы хотите обнулить его, выполните:

SingleBlock::~SingleBlock()

{    x = y = 0 ; }
0 голосов
/ 18 декабря 2009

Да, это можно ожидать время от времени. В то время как new резервирует место для данных, delete просто делает недействительным указатель, созданный с помощью new, позволяя записывать данные в ранее зарезервированные местоположения; это не обязательно удаляет данные. Однако вы не должны полагаться на такое поведение, потому что данные в этих местах могут измениться в любое время, что может привести к неправильной работе вашей программы. Вот почему после того, как вы используете delete для указателя (или delete[] для массива, выделенного с new[]), вы должны присвоить ему NULL, чтобы вы не могли изменить недопустимый указатель, предполагая, что вы не будете выделите память, используя new или new[], прежде чем снова использовать этот указатель.

0 голосов
/ 18 декабря 2009

Это пока не обнулит / не изменит память ... но в какой-то момент коврик будет вырван из-под ваших ног.

Нет, это, конечно, не предсказуемо: это зависит от того, насколько быстро выделяется / освобождается память.

...