2

I'm trying to split a long string into tokens, stored into a NULL terminated string array. To do this, I double the array size with realloc each time it's full. But valgrind is telling me that there are some important problems. Here's the code:

char** split_token(char* str,char* delimiter)
{
int token_buffer_size=256;
int nb_token=0;
char* token;
char** tab_token=calloc(token_buffer_size,sizeof(char*));
test_ptr(tab_token,PARAM_MACRO_TEST);
token=strtok(str,delimiter);
while(token!=NULL) 
{
    if(nb_token>=token_buffer_size)
    {
        token_buffer_size=token_buffer_size*2;
        tab_token=realloc(tab_token,token_buffer_size);
        test_ptr(tab_token,PARAM_MACRO_TEST);
    }
    printf("nb_token : %d\n",nb_token);
    tab_token[nb_token]=calloc(strlen(token)+1,sizeof(char));
    test_ptr(tab_token[nb_token],PARAM_MACRO_TEST);
    strncpy(tab_token[nb_token],token,sizeof(char)*strlen(token));
    nb_token++;
    token=strtok(NULL,delimiter);
}
tab_token[nb_token+1]=NULL;
return tab_token;
}

test_ptr() being a basic function testing if a ptr is NULL or not. The function is called with a long string to split (str), and a delimiter for strtok ("\n" here). When firing valgrind, here's what I get:

nb_token : 256
==8737== Invalid write of size 8
==8737==    at 0x59E8E98: split_token (parse.c:27)
==8737==    by 0x59EAA13: recdir (libplugin.c:439)
==8737==    by 0x401C09: execute_plugin (loadlib.c:53)
==8737==    by 0x400EF9: main (main.c:23)
==8737==  Address 0x5470ce0 is not stack'd, malloc'd or (recently) free'd
==8737== 
==8737== Invalid read of size 8
==8737==    at 0x59E8EB9: split_token (parse.c:28)
==8737==    by 0x59EAA13: recdir (libplugin.c:439)
==8737==    by 0x401C09: execute_plugin (loadlib.c:53)
==8737==    by 0x400EF9: main (main.c:23)
==8737==  Address 0x5470ce0 is not stack'd, malloc'd or (recently) free'd
==8737== 
==8737== Invalid read of size 8
==8737==    at 0x59E8EFA: split_token (parse.c:29)
==8737==    by 0x59EAA13: recdir (libplugin.c:439)
==8737==    by 0x401C09: execute_plugin (loadlib.c:53)
==8737==    by 0x400EF9: main (main.c:23)
==8737==  Address 0x5470ce0 is not stack'd, malloc'd or (recently) free'd
==8737== 
nb_token : 257

So, after reallocating the tab (thus having a size 512 tab_token), it seems that storing a string into tab_token[256] fails. I have absolutely no idea why. Thanks for your attention.

1
  • tab_token[nb_token+1]=NULL; is off by one; should be tab_token[nb_token]=NULL; (after checking for size of pointer array) Commented May 15, 2014 at 23:14

1 Answer 1

3

This:

tab_token=realloc(tab_token,token_buffer_size);

Should be:

tab_token=realloc(tab_token, token_buffer_size*sizeof(*tab_token));

calloc() uses item-count and item-size, but realloc() uses bytes. account for that in your resize.

Sign up to request clarification or add additional context in comments.

2 Comments

@user3618511 Heh. get used to it, you have plenty more in the barrel before the the career winds down; believe me.
It's a common enough error that OpenBSD developers created a reallocarray() function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.