分段错误-无效自由未解决-C

分段错误-无效自由未解决-C,c,pointers,memory-management,gdb,heap-memory,C,Pointers,Memory Management,Gdb,Heap Memory,错误 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 /li

错误

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。非法自由

例如:

无效的free()
在0x4004FFDF:free(vg_clientmalloc.c:577)
通过0x80484C7:main(tests/doublefree.c:10)
地址0x3807F7B4是大小为177 free'd的块中的0字节 在0x4004FFDF:free(vg_clientmalloc.c:577) 通过0x80484C7:main(测试/doublefree.c:10)

Memcheck通过以下方式跟踪程序分配的块: malloc/new,因此它可以准确地知道参数是否 免费/删除是否合法。在此,此测试程序已释放 同一街区两次。与非法读/写错误一样,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,问题会在不同的部分发现,但总是出现无效自由问题
  • 鉴于上述情况,我的问题如下:

    在这种情况下,如何确保指针指向正确


    您认为这个问题的原因是什么?

    它不为null并不保证它是一个有效的分配内存。 我们需要更多的背景来理解确切的问题

    但是,当您释放内存时,指针会继续存储无效地址,因为指针是按值传递给free函数的,您可以看到更好的解释。 基于此,我猜测您正在尝试释放同一指针两次

    一个临时的方法是在释放指针后手动将其设置为null,这样您可以更好地隔离问题并尝试找到问题的真正根源:

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

    这是我今年看到的最完整的问题。做得好!那么
    XtFree(str)呢?另外,FWIW,
    free(空)完全有效。您可以释放两次或使用无效指针。我不确定问题是什么……它不为null并不保证它是一个有效的分配内存。@moffeltje:你一定是在开玩笑。没有MCVE。。。谢谢@danielfranca,我尝试用if(call_data->text->ptr){XtFree(call_data->text->ptr);}包装,但没有成功。我会试试你的黑客建议,然后反馈给你。另外,谢谢你的推荐。