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)
 
     
    