Segmentation fault - Invalid free unresolved - C

1.4k views Asked by At

Error

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
...

Details

To make sure what the problem was I did a memory check:

==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 

Possible causes

And according to Valgrind official documentation:

4.2.4. Illegal frees

For example:

Invalid free()
at 0x4004FFDF: free (vg_clientmalloc.c:577)
by 0x80484C7: main (tests/doublefree.c:10)
Address 0x3807F7B4 is 0 bytes inside a block of size 177 free'd at 0x4004FFDF: free (vg_clientmalloc.c:577) by 0x80484C7: main (tests/doublefree.c:10)

Memcheck keeps track of the blocks allocated by your program with malloc/new, so it can know exactly whether or not the argument to free/delete is legitimate or not. Here, this test program has freed the same block twice. As with the illegal read/write errors, Memcheck attempts to make sense of the address freed. If, as here, the address is one which has previously been freed, you will be told that -- making duplicate frees of the same block easy to spot. You will also get this message if you try to free a pointer that doesn't point to the start


Code

As you can see, I only free after checking if it is NOT NULL.

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

Evaluation (personal)

  1. Since I'm checking for existence, the problem seems to be the pointer not pointing to the start of the heap block.
  2. Running gdb more times, the problem is found in different parts, but it always comes to the Invalid Free problem.

Given the context, my questions are:

How can I make sure the pointer is pointing correctly in this case?

What do you think is the cause of this problem?

1

There are 1 answers

1
dfranca On

It's being not null doesn't guarantee that it's a valid allocated memory. We need more context to understand the exact problem.

But, when you free the memory the pointer keeps storing the invalid address, as the pointer is passed by value to the free function, as you can see a better explanation here. Based on that my guess is that you are trying to free the same pointer twice.

A temporary hack would be to manually set the pointer to null after free it, so you can better isolate the problem and try to find the real root of that:

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