Home > Enterprise >  string splitter in C - dynamic memory
string splitter in C - dynamic memory

Time:09-11

I am trying to enhance the string splitter by splits on : char. Original version can be found at string splitter - how is it working

I do not want to use MAX_TOKEN_SIZE, I want the buffer to be just enough to hold each token. I added malloc and realloc as follows but I am getting free(): double free detected in tcache 2 error which I do not understand. How am I double freeing ? Thanks for all your help.

PS: Based on Gerhardh's comments, I modified the code as follows, but now I am getting segfault.

PS: Based on user3121023's comments, I added parenthesis around *token in 2 places and it works now.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

# define GROWBY 32

const char* splitter(const char *str, char delimiter, char **token) {

    size_t i = 0;
    size_t buflen = 32;
    while (*str) {
       if ( i ==  buflen) {
           buflen  = GROWBY;
           printf("gowing buffer\n");
           char *new_token = realloc(*token, buflen * sizeof **token);
           if (new_token == NULL){
               fprintf(stderr, "Out of Memory");
               abort();
           }
           *token = new_token; //set the new pointer to old pointer
       }
       char c = *(str  );

       if (c == delimiter)
           break;

       (*token)[i  ] = c; //user3121023
   }

   (*token)[i] = '\0';  /* set the null terminator, user3121023 */

   return str;
} 

int main(){
    
    const char *env = 
  "/bin/svsgerertegdfyufdujhdcjxbcn:/sbin:::/usr/bin/46526vw67vxshgshnxxcxhcgbxhcbxn";

   while (*env){
       char *token = malloc(GROWBY * sizeof(char));
       env = splitter(env, ':', &token);  
       if (token[0] == '\0') {
           strcpy(token, "./");            
       }
       printf("%s\n", token)  ;
       free(token);
   }

   return 0;
}

CodePudding user response:

Try using strcspn to advance to the next delimiter.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* splitter(const char *str, char *delimiter, char **token) {
    size_t buflen = 0;
    size_t extra = 0;

    buflen = strcspn ( str, delimiter); // characters to next delimiter
    extra = 1;
    if ( ! buflen) {
        extra = 3; // need space for "./" copy in main
    }
    char *new_token = realloc(*token, ( buflen   extra) * sizeof **token);
    if (new_token == NULL){
        fprintf(stderr, "Out of Memory");
        abort();
    }
    *token = new_token; //set the new pointer to old pointer
    strncpy ( *token, str, buflen);

    (*token)[buflen] = 0;

    str  = buflen;
    if ( *str) {
        str  = 1;
    }
    return str;
}

int main(void){

    const char *env =
  "/bin/svsgerertegdfyufdujhdcjxbcn:/sbin:::/usr/bin/46526vw67vxshgshnxxcxhcgbxhcbxn";

   while (*env){
       char *token = NULL;
       env = splitter(env, ":", &token); // note " instead of '
       if (token[0] == '\0') {
           strcpy(token, "./");
       }
       printf("%s\n", token)  ;
       free(token);
   }
   return 0;
}
  • Related