2013-03-12 2 views
0

При анализе ядра, сбрасываемого после SIGABRT, gdb говорит, что моя последняя строка кода, выполняемая (перед вводом кода библиотеки), является назначением указателю char, поскольку показано ниже:Сигнал 6 (SIGABRT) при назначении переменной null (C++)

GDB:

(gdb) bt full 
#0 0x006337a2 in _dl_sysinfo_int80() from /lib/ld-linux.so.2 
No symbol table info available. 
#1 0x00674815 in raise() from /lib/tls/libc.so.6 
No symbol table info available. 
#2 0x00676279 in abort() from /lib/tls/libc.so.6 
No symbol table info available. 
#3 0x006a8cca in __libc_message() from /lib/tls/libc.so.6 
No symbol table info available. 
#4 0x006af55f in _int_free() from /lib/tls/libc.so.6 
No symbol table info available. 
#5 0x006af93a in free() from /lib/tls/libc.so.6 
No symbol table info available. 
#6 0x00d0b14e in __builtin_delete() from /usr/lib/libstdc++-libc6.1-1.so.2 
No symbol table info available. 
#7 0x0808181c in MyObject::~MyObject (this=0x84f4db0, __in_chrg=3) at ./MyObject.cpp:16 
    this = (MyObject *) 0x84f4db0 

myobject.cpp: 16 листинг:

12: ... 
13: MyObject::~MyObject() { 
14: if (this->string != NULL) { 
15:  delete this->string; 
16:  this->string = NULL; 
17: } 
18: } 
19: ... 

Прежде всего, я не понимаю, почему линия 16 Wou ld приводит к тому, что стек вызовов. Было бы разумнее, если бы это было результатом выполнения строки 15, той, которая была с оператором delete (если только «строка 16» не представляет код, выполняемый после код деструктора для освобождения выделенной для этого объекта памяти, просто угадывая здесь).

Помимо этого, может ли кто-нибудь указать способ правильно отладить это ядро?

+0

Это результат строки 15. – UmNyobe

+1

Заметим, что 1) нулевая проверка является излишней, так как удаление делает это тоже, и 2) присвоение нулевого значения также излишне, поскольку объект не существует после завершения dtor. Кроме этого, вы можете создать тестовый файл? и, пожалуйста, опубликуйте хотя бы сообщение об ошибке, которое выдается glibc прямо перед прерыванием. Мое лучшее предположение, что вы хотели 'delete []' вместо 'delete'. – PlasmaHH

+0

К сожалению, я не могу создать тестовый файл менее чем за один месяц (код действительно большой и объединенный). 'this-> string' имеет тип' char * '. У меня нет сообщения об ошибке, выпущенного glibc. Это вся информация, которую я имею/могу поделиться. – freitass

ответ

3

Какой тип this->string есть? Это массив символов? Затем вы должны использовать delete [] this->string. Является ли это указателем на объект? Затем этот объект либо уже удален, либо указатель не был нулевым, либо объект никогда не был создан, а указатель остался унифицированным.

+0

Тип 'this-> string' -' char * '. Я должен сказать вам, что этот код работал несколько часов (и этот фрагмент кода выполнялся несколько раз) перед сбоем. Если проблема заключалась в использовании 'delete' вместо' delete [] ', не должна ли она сбой при первом запуске? – freitass

+0

@freitass: Когда вы вызываете UB, может случиться anythign. – PlasmaHH

+0

@PlasmaHH: Что такое UB? – freitass

0

Он указывает на следующую строку, которая составляет , о выполнении, которая является строкой 16 в вашем случае, последняя выполненная инструкция/выражение была строкой 15 и она разбилась на этой строке.

Трудно сказать из вашего сообщения, что здесь неправильно.

+0

Пожалуйста, скажи мне, что я не сумасшедший. Может ли он отличаться от указания на выполняемую линию и строки * о *, которая должна быть выполнена? Потому что я совершенно уверен, что это первый раз, когда я это вижу. Или, по крайней мере, это первый раз, когда интерпретация «выполняемой линии» не имеет смысла. – freitass

+0

Отладчик, любой из тех, что я использовал, всегда указывает на строку, прошедшую только что выполненную, когда она разбилась. Я не говорю, когда вы проходите через это. –

+0

Может быть, я сейчас что-то перемешиваю. В следующий раз я обращу внимание. Благодаря! – freitass

1

Фактическое крушение произошло на этой линии:

15:  delete this->string; 

Крушение произошло из-за звонить в abort внутри __libc_message. Эта последняя процедура напечатали сообщение на стандартной ошибки, и сообщение выглядело как-то

*** glbc detected: double free or heap corruption at ... *** 

Использование Valgrind или AddressSanitizer: они указывают вам прямо на эту проблему.

Я не понимаю, почему строка 16 приведет к тому, что стек вызовов.

Когда вы смотрите на стек вызовов, которые привели к raise системному вызову, вы должны понимать, что CALL инструкции помещает адрес следующей команды, которая будет выполнено в стеке, перед передачей управления в и это следующая инструкция, которую GDB показывает вам в backtrace (все отладчики делают это). Эта следующая инструкция может быть на текущей строке, следующей строке или на 20 строк вниз.

+0

Пожалуйста, см. Мой комментарий/вопрос в ответ Тони Лев. И да, я намерен использовать Valgrind, чтобы очистить этот лук. :-) – freitass

Смежные вопросы