Ошибка сегментации - Недопустимый свободный, неразрешенный - C
ошибка
Program received signal SIGSEGV, Segmentation fault.
0x007068ef in _int_malloc () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install IV_prepaid_oam-37beta-1433949053.x86_64
(gdb) where
#0 0x007068ef in _int_malloc () from /lib/libc.so.6
#1 0x00707d9e in malloc () from /lib/libc.so.6
#2 0x00642fe8 in XtMalloc () from /usr/lib/libXt.so.6
#3 0x0097783f in XmTextFieldGetString () from /usr/lib/libXm.so.4
#4 0x080ee9c1 in check_code (w=0x839d588, client_data=0x0,
call_data=0xffffaf1c) at debit_rt.c:2026
#5 0x006435c6 in XtCallCallbackList () from /usr/lib/libXt.so.6
#6 0x0097637a in ?? () from /usr/lib/libXm.so.4
#7 0x0097fdbe in ?? () from /usr/lib/libXm.so.4
#8 0x00669d96 in ?? () from /usr/lib/libXt.so.6
#9 0x0066a72a in XtSetValues () from /usr/lib/libXt.so.6
#10 0x0067d92a in XtVaSetValues () from /usr/lib/libXt.so.6
#11 0x080eea0d in check_code (w=0x839d588, client_data=0x0,
call_data=0xffffba8c) at debit_rt.c:2030
#12 0x006435c6 in XtCallCallbackList () from /usr/lib/libXt.so.6
#13 0x0097637a in ?? () from /usr/lib/libXm.so.4
#14 0x00981fea in XmTextFieldSetString () from /usr/lib/libXm.so.4
#15 0x00982454 in ?? () from /usr/lib/libXm.so.4
#16 0x0092ab39 in XmTextSetString () from /usr/lib/libXm.so.4
#17 0x080eb19d in set_widget_val (w=0x839d588, val=0x84b8ce0 "000024390")
at debit_rt.c:628
#18 0x080eb2fe in display_rate (btn_num=0) at debit_rt.c:654
#19 0x080ed448 in redraw_rate_table (table_num=100, table_type=66 'B',
reread=1) at debit_rt.c:1428
#20 0x080ee716 in rt_modify2 () at debit_rt.c:1928
#21 0x080c97a6 in apply_cb (w=0x84958d0, client_data=0x0,
call_data=0xffffc0a4) at debit_cbs.c:1823
...
подробности
Чтобы убедиться, в чем проблема, я проверил память:
==26407== Invalid free() / delete / delete[] / realloc()
==26407== at 0x4026CAF: free (vg_replace_malloc.c:446)
==26407== by 0x642E51: XtFree (in /usr/lib/libXt.so.6.0.0)
==26407== by 0x97658C: ??? (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x981FE9: XmTextFieldSetString (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x982453: ??? (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x92AB38: XmTextSetString (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x80EB196: set_widget_val (debit_rt.c:628)
==26407== by 0x80EB2F7: display_rate (debit_rt.c:654)
==26407== by 0x80ED441: redraw_rate_table (debit_rt.c:1428)
==26407== by 0x80EE70F: rt_modify2 (debit_rt.c:1928)
==26407== by 0x80C97A5: apply_cb (debit_cbs.c:1823)
==26407== by 0x643630: XtCallCallbackList (in /usr/lib/libXt.so.6.0.0)
==26407== Address 0x7f01380 is 0 bytes inside a block of size 6 free'd
==26407== at 0x4026CAF: free (vg_replace_malloc.c:446)
==26407== by 0x642E51: XtFree (in /usr/lib/libXt.so.6.0.0)
==26407== by 0x80EEA16: check_code (debit_rt.c:2031)
==26407== by 0x6435C5: XtCallCallbackList (in /usr/lib/libXt.so.6.0.0)
==26407== by 0x976379: ??? (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x981FE9: XmTextFieldSetString (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x982453: ??? (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x92AB38: XmTextSetString (in /usr/lib/libXm.so.4.0.3)
==26407== by 0x80EB196: set_widget_val (debit_rt.c:628)
==26407== by 0x80EB2F7: display_rate (debit_rt.c:654)
==26407== by 0x80ED441: redraw_rate_table (debit_rt.c:1428)
==26407== by 0x80EE70F: rt_modify2 (debit_rt.c:1928) I
Возможные причины
И согласно официальной документации Valgrind:
4.2.4. Незаконные освобождения
Например:
Неверно бесплатно ()
в 0x4004FFDF: бесплатно (vg_clientmalloc.c:577)
по 0x80484C7: основной (тесты /doublefree.c:10)
Адрес 0x3807F7B4 составляет 0 байтов внутри блока размером 177 free'd при 0x4004FFDF: free (vg_clientmalloc.c:577) по 0x80484C7: main (tests /doublefree.c:10)Memcheck отслеживает блоки, выделенные вашей программой с помощью malloc / new, поэтому он может точно знать, является ли аргумент free / delete допустимым или нет. Здесь эта тестовая программа освободила один и тот же блок дважды. Как и в случае недопустимых ошибок чтения / записи, Memcheck пытается разобраться с освобожденным адресом. Если, как здесь, адрес является тем, который был ранее освобожден, вам скажут, что - облегчая обнаружение повторяющихся освобождений одного и того же блока. Вы также получите это сообщение, если попытаетесь освободить указатель, который не указывает на начало
Код
Как видите, я освобождаюсь только после проверки, не является ли он НЕДЕЙСТВИТЕЛЬНЫМ.
void check_code( w, client_data, call_data )
Widget w;
caddr_t client_data;
XmTextVerifyCallbackStruct *call_data;
{
char *str;
char *test_str;
test_str = (w==rt_source) ? ANY_SOURCE_STRING : ANY_DEST_STRING;
/* If the new value is the special string, then allow it */
/* Note it will always be replacing any old contents */
if( call_data->text->ptr != NULL )
if( strcmp( call_data->text->ptr, test_str ) == 0 )
return;
/* If the old value of the text widget was the special string, */
/* delete it and replace it with any new string */
str = XmTextFieldGetString( w ); /* This get string tries to allocate memory */
if( strcmp( str, test_str ) == 0 )
if( call_data->text->ptr != NULL ) /* Make sure it exist before freeing */
{
XtVaSetValues( w, XmNvalue, call_data->text->ptr, NULL ); /* Existis, so, pointing incorr. */
XtFree( call_data->text->ptr ); /* Same as above line */
call_data->text->length = 0;
}
else
XtVaSetValues( w, XmNvalue, "", NULL );
XtFree( str );
/* Perform the normal check for new contents (GPRS allows characters) */
if ( rt_type == VOICE_RT )
check_digits( w, client_data, call_data );
}
Оценка (личная)
- Поскольку я проверяю существование, проблема, похоже, заключается в том, что указатель не указывает на начало блока кучи.
- При повторном запуске gdb проблема обнаруживается в разных частях, но всегда возникает проблема Invalid Free.
Учитывая контекст, мои вопросы:
Как я могу убедиться, что указатель правильно указывает в этом случае?
Как вы думаете, является причиной этой проблемы?
1 ответ
То, что оно не равно нулю, не гарантирует, что это правильная выделенная память. Нам нужно больше контекста, чтобы понять точную проблему.
Но когда вы освобождаете память, указатель сохраняет неправильный адрес, так как указатель передается по значению в свободную функцию, как вы можете увидеть более подробное объяснение здесь. Исходя из этого, я предполагаю, что вы пытаетесь освободить один и тот же указатель дважды.
Временным хаком было бы вручную установить нулевой указатель после его освобождения, чтобы вы могли лучше изолировать проблему и попытаться найти истинный корень этого:
if( strcmp( str, test_str ) == 0 )
if( call_data->text->ptr != NULL ) /* Make sure it exist before freeing */
{
XtVaSetValues( w, XmNvalue, call_data->text->ptr, NULL ); /* Existis, so, pointing incorr. */
XtFree( call_data->text->ptr ); /* Same as above line */
call_data->text->ptr = NULL;
call_data->text->length = 0;
}