Как может произойти сбой операции delete [] во время успешного завершения деструктора? (в C ++) - PullRequest
3 голосов
/ 30 августа 2011

У меня есть класс Foo, в котором есть (простой) деструктор.

Некоторые другие классы содержат массив объектов Foo (называемых дураками), в деструкторе этого класса я делаю:

delete[] foolist;

Это дает сбой (GDB показывает, что происходит сбой именно в этой строке).Однако, используя распечатки, я вижу, что все элементы в foolist без проблем завершают работу своего деструктора (количество запущенных деструкторов также равно количеству объектов, выделенных в этом массиве, поэтому они все разрушаются).В коде также нет другого удаления для foolist.

Я также убедился, что foolist действительно инициализирован как массив, таким образом:

foolist = new Foo[number];

Ошибка:

*** glibc detected *** /home/bas/projects/trunk/main:
free(): invalid next size (fast): 0x080a0e80 ***

Что может привести к сбою delete [] в этом случае?

Заранее спасибо!

Как и здесь, спрашивается вывод команды valgind (StatementNode это Foo, а programNodeкласс, содержащий список Foo)

==4111== 1 errors in context 1 of 2:
==4111== Invalid write of size 4
==4111==    at 0x804B6FA: Parser::parseProgram(std::string) (statementnode.h:35)
==4111==    by 0x80764D4: main (parser.h:35)
==4111==  Address 0x42d9bdc is 4 bytes after a block of size 32 alloc'd
==4111==    at 0x4025F53: operator new[](unsigned int) (vg_replace_malloc.c:299)
==4111==    by 0x804A81E: Parser::parseProgram(std::string) (programnode.h:21)
==4111==    by 0x80764D4: main (parser.h:35)

StatementNode: 35 - создание совершенно другого объекта.ProgramNode: 21 - создание глупого / списка StatementNodes. Надеюсь, это поможет.

Ответы [ 3 ]

7 голосов
/ 30 августа 2011

Оператор delete выполняет 2 функции под капотом

  1. Деструкторы запуска
  2. Свободная память

Учитывая, что распечатка подтверждает, что происходит # 1наиболее вероятная причина - сбой во время фактического освобождения памяти (это также указывается в сообщении).Обычно это указывает на то, что память повреждена другой частью вашей программы.

Вы пытались запустить вашу программу под valgrind?

6 голосов
/ 30 августа 2011

Похоже, наш старый добрый приятель "неопределенное поведение".

Возможно foolist удаляется дважды. Вы перегружали конструктор копирования и оператор присваивания класса? Если нет, вы должны прочитать это: Что такое правило трех?

2 голосов
/ 30 августа 2011

Вы могли бы дважды удалить его - даже непреднамеренно, нарушив Правило Трех.Вы могли бы изменить значение указателя, например, увеличивая его.Вы можете полиморфно преобразовать его, например, Base* ptr = new Derived[size]; delete[] ptr;, что также является неопределенным поведением.

Урок: всегда, всегда, всегда используйте умный указатель.

...