I have a simple program to split the input string based on the delim. The algorithm is as follows:
Count the size of batches that I am going to divide the original input to.
Malloc the 2D pointer results according to count size + 1 (last one make it NULL)
Call strsep to cut the source piece by piece (token)
- Malloc the pointer results[i] by strlen(token)
- strcpy(results[i], token)
- Return results
I couldn't figure out why these two free() statement will cause me errors. On line 51:
free(*(tokens + i));
This line gave me the following error:
free(): invalid pointer
if I commented out this line, on line 54:
free(tokens);
Gave me the following error:
free(): invalid next size (fast)
I went through the discussions about these two errors, but I still couldn't figure out why these were causing problems to my program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char** str_split(char *str, const char *delim)
{
char *token;
char **results;
int count = 0;
int i;
for( i = 0; i < strlen(str); i++ )
//TODO: check delim format
// assume to be one char string for now
if( str[i] == *delim )
count++;
count++;
results = (char**) malloc(sizeof(char*) * count); /* line 21 */
int index = 0;
while( (token = strsep(&str, delim)) != NULL )
{
int size = strlen(token);
results[index] = (char*) malloc(sizeof(char*) * size); /* line 27 */
strcpy( results[index], token );
index++;
}
results[index] = NULL; /* line 31 */
return results;
}
int main()
{
char source[] = "name id ip";
char **tokens;
printf("source=[%s]\n\n", source);
tokens = str_split(source, " ");
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("batch=[%s]\n", *(tokens + i));
free(*(tokens + i)); /* line 51*/
}
printf("\n");
free(tokens); /* line 54 */
}
return 0;
}
I also tried gdb to see more detail to what was going on. I was able to examine the pointer on line 51:
gdb> x /s *(tokens+i) 0x602030: "name"
Also on line 54:
gdb> x /s *tokens 0x602010: "0 `"
I also tried Valgrid to examine my compiled file but I didn't know how to interpret this analysis:
==26070== Command: ./str_parse
==26070==
==26070== Invalid write of size 8
==26070== at 0x40086D: str_split (str_parse.c:31)
==26070== by 0x4008D4: main (str_parse.c:43)
==26070== Address 0x51fc058 is 0 bytes after a block of size 24 alloc'd
==26070== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26070== by 0x4007CB: str_split (str_parse.c:21)
==26070== by 0x4008D4: main (str_parse.c:43)
==26070==
==26070== Invalid read of size 8
==26070== at 0x40094D: main (str_parse.c:48)
==26070== Address 0x51fc058 is 0 bytes after a block of size 24 alloc'd
==26070== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26070== by 0x4007CB: str_split (str_parse.c:21)
==26070== by 0x4008D4: main (str_parse.c:43)
==26070==
==26070==
==26070== HEAP SUMMARY:
==26070== in use at exit: 0 bytes in 0 blocks
==26070== total heap usage: 4 allocs, 4 frees, 88 bytes allocated
==26070==
==26070== All heap blocks were freed -- no leaks are possible
==26070==
==26070== For counts of detected and suppressed errors, rerun with: -v
==26070== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)