Pointer confusion with passing string array -- Segmentation fault

Discussion in 'C Programming' started by Goh, Yong Kwang, Apr 3, 2004.

  1. I'm trying to create a function that given a string, tokenize it and
    put into a dynamically-sized array of char* which is in turn also
    dynamically allocated based on the string token length.

    I call the function using this code fragement in my main function:
    ---
    char** arg_array;
    arg_count = create_arg_array(command, argument, arg_array);

    for(count = 0; count < arg_count; count++)
    printf("arg_array[%d]: %s\n", count, arg_array[count]);
    ---
    And it always crashes with a segmentation fault when going into the
    for loop to print out the array of strings. Why does it crash when
    I've already called malloc and realloc (inside create_arg_array()
    function) to reserve some memory for the string array?

    The create_arg_array is given below.
    What's wrong with this function?
    ---
    size_t create_arg_array(char* file, char* arg, char** array){
    size_t count;
    char* argument;

    count = 1;
    /* 1 for the filename and 1 for the terminating NULL ptr. */
    array = (char**) malloc(count * sizeof(char*));

    array[0] = (char*) malloc(strlen(file) + 1);
    strcpy((*array)[0], file);

    if(arg != NULL){
    argument = strtok(arg, " \n");
    if(argument != NULL){
    array = (char**) realloc(array, (count + 1) * sizeof(char*));
    array[count] = (char*) malloc(strlen(argument) + 1);
    strcpy(array[count], argument);
    count++;
    }
    while((argument = strtok(NULL, " \n")) != NULL){
    array = (char**) realloc(array, (count + 1) * sizeof(char*));
    array[count] = (char*) malloc(strlen(argument) + 1);
    strcpy(array[count], argument);
    count++;
    }
    }
    ++count;
    array = (char**) realloc(array, (count * sizeof(char*)));
    array[count-1] = NULL;

    return count-1; /* Minus 1 for the ending NULL */
    }
    ---
    I thought the address returned by realloc and malloc is lost when I
    return to main function and I've also tried changing the function to
    accept a pointer to the array of string (char***) but it doesn't help.

    Any advice appreciated.
    Thank you.

    Goh, Yong Kwang
    Singapore
    Goh, Yong Kwang, Apr 3, 2004
    #1
    1. Advertising

  2. Goh, Yong Kwang

    Jack Klein Guest

    On 2 Apr 2004 17:31:23 -0800, (Goh, Yong
    Kwang) wrote in comp.lang.c:

    > I'm trying to create a function that given a string, tokenize it and
    > put into a dynamically-sized array of char* which is in turn also
    > dynamically allocated based on the string token length.
    >
    > I call the function using this code fragement in my main function:
    > ---
    > char** arg_array;
    > arg_count = create_arg_array(command, argument, arg_array);
    >
    > for(count = 0; count < arg_count; count++)
    > printf("arg_array[%d]: %s\n", count, arg_array[count]);
    > ---
    > And it always crashes with a segmentation fault when going into the
    > for loop to print out the array of strings. Why does it crash when
    > I've already called malloc and realloc (inside create_arg_array()
    > function) to reserve some memory for the string array?
    >
    > The create_arg_array is given below.
    > What's wrong with this function?


    The main answer to your primary question is covered in this
    newsgroup's FAQ, specifically:

    http://www.eskimo.com/~scs/C-faq/q4.8.html

    > ---
    > size_t create_arg_array(char* file, char* arg, char** array){
    > size_t count;
    > char* argument;
    >
    > count = 1;
    > /* 1 for the filename and 1 for the terminating NULL ptr. */
    > array = (char**) malloc(count * sizeof(char*));
    >
    > array[0] = (char*) malloc(strlen(file) + 1);


    Casting the pointer returned by malloc() is unnecessary in C and
    considered bad form by most experienced C programmers. At best it is
    useless, a redundant cast. At worst it silences an important compiler
    diagnostic if you neglected to include <stdlib.h> to have a proper
    prototype in scope.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Apr 3, 2004
    #2
    1. Advertising

  3. Goh, Yong Kwang

    Al Bowers Guest

    Goh, Yong Kwang wrote:
    > I'm trying to create a function that given a string, tokenize it and
    > put into a dynamically-sized array of char* which is in turn also
    > dynamically allocated based on the string token length.
    >


    ..........snip...........

    > ---
    > size_t create_arg_array(char* file, char* arg, char** array){
    > size_t count;
    > char* argument;
    >


    > ---
    > I thought the address returned by realloc and malloc is lost when I
    > return to main function and I've also tried changing the function to
    > accept a pointer to the array of string (char***) but it doesn't help.
    >


    A char *** parameter would be correct. But you need to correct
    the logic errors. Another approach would be to define a
    data type that will contain all the data that you need.

    like:
    typedef struct DATA
    {
    char *fdata /* contents of the entire file */
    char **pdata /* An array of pointers to the file data */
    size_t count /* A count of the array of pointers */
    } DATA;

    Then you can write functions to manipulate this datatype.

    Ex.

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

    #define FNAME "test.txt" /* File name goes here */

    /*test.txt contents:

    Bill:JOHN:HARRY:AL:WILLIAM:
    FRANK:LARRY:RON

    */

    typedef struct DATA
    {
    char *fstring;
    char **pstring;
    size_t count;
    } DATA;

    DATA getDATA(const char *fname, const char *delim);
    void freeDATA(DATA *p);
    void printDATA(DATA *p);

    int main(void)
    {
    DATA data = getDATA(FNAME, ":\n");

    printDATA(&data);
    freeDATA(&data);
    return 0;
    }

    DATA getDATA(const char *fname, const char *delim)
    {
    FILE *fp;
    DATA p = {NULL};
    char *tmp, buf[64], **tmpp;
    size_t sz;

    if((fp = fopen(fname,"r")) == NULL) return p;
    for(sz = 0 ; (fgets(buf,sizeof buf, fp)); )
    {
    tmp = realloc(p.fstring, (sz += strlen(buf))+1);
    if(tmp == NULL)
    {
    freeDATA(&p);
    break;
    }
    if(!p.fstring) *tmp = '\0';
    p.fstring = tmp;
    strcat(p.fstring,buf);
    }
    fclose(fp);
    if(p.fstring)
    {
    for(tmp = strtok(p.fstring,delim) ; tmp;
    tmp = strtok(NULL,delim))
    {
    tmpp = realloc(p.pstring, (p.count+1)*sizeof(*tmpp));
    if(tmpp == NULL)
    {
    freeDATA(&p);
    break;
    }
    tmpp[p.count++] = tmp;
    p.pstring = tmpp;
    }
    }
    return p;
    }

    void freeDATA(DATA *p)
    {
    free(p->fstring);
    free(p->pstring);
    p->fstring = NULL;
    p->pstring = NULL;
    p->count = 0;
    return;
    }

    void printDATA(DATA *p)
    {
    size_t i;

    for(i = 0; i < p->count; i++)
    printf("%u. %s\n",i,p->pstring);
    return;
    }

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
    Al Bowers, Apr 3, 2004
    #3
  4. On 2 Apr 2004 17:31:23 -0800, (Goh, Yong
    Kwang) wrote:

    >I'm trying to create a function that given a string, tokenize it and
    >put into a dynamically-sized array of char* which is in turn also
    >dynamically allocated based on the string token length.
    >
    >I call the function using this code fragement in my main function:
    >---
    >char** arg_array;
    >arg_count = create_arg_array(command, argument, arg_array);


    After you return from create_arg_array, arg_array has not been updated
    with the address that was malloc'ed in the function. C always passes
    by value.

    >
    >for(count = 0; count < arg_count; count++)
    > printf("arg_array[%d]: %s\n", count, arg_array[count]);
    >---
    >And it always crashes with a segmentation fault when going into the
    >for loop to print out the array of strings. Why does it crash when
    >I've already called malloc and realloc (inside create_arg_array()
    >function) to reserve some memory for the string array?
    >
    >The create_arg_array is given below.
    >What's wrong with this function?
    >---
    >size_t create_arg_array(char* file, char* arg, char** array){
    > size_t count;
    > char* argument;
    >
    > count = 1;
    > /* 1 for the filename and 1 for the terminating NULL ptr. */
    > array = (char**) malloc(count * sizeof(char*));


    Don't cast the return from malloc. It cannot help and can hurt.

    >
    > array[0] = (char*) malloc(strlen(file) + 1);
    > strcpy((*array)[0], file);
    >
    > if(arg != NULL){
    > argument = strtok(arg, " \n");
    > if(argument != NULL){
    > array = (char**) realloc(array, (count + 1) * sizeof(char*));
    > array[count] = (char*) malloc(strlen(argument) + 1);
    > strcpy(array[count], argument);
    > count++;
    > }
    > while((argument = strtok(NULL, " \n")) != NULL){
    > array = (char**) realloc(array, (count + 1) * sizeof(char*));
    > array[count] = (char*) malloc(strlen(argument) + 1);
    > strcpy(array[count], argument);
    > count++;
    > }
    > }
    > ++count;
    > array = (char**) realloc(array, (count * sizeof(char*)));
    > array[count-1] = NULL;
    >
    > return count-1; /* Minus 1 for the ending NULL */
    >}
    >---
    >I thought the address returned by realloc and malloc is lost when I
    >return to main function and I've also tried changing the function to
    >accept a pointer to the array of string (char***) but it doesn't help.


    Yes it does if you use it properly. Your calling statement needs to
    specify &arg_array. Inside the function, every place you currently
    use array you need to use (*array). This will cause the function to
    automatically update arg_array in the calling function.

    >
    >Any advice appreciated.
    >Thank you.
    >
    >Goh, Yong Kwang
    >Singapore
    >




    <<Remove the del for email>>
    Barry Schwarz, Apr 3, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Van Extergem

    Function pointer results in segmentation fault.

    Chris Van Extergem, May 1, 2006, in forum: C Programming
    Replies:
    5
    Views:
    849
    Chris Van Extergem
    May 2, 2006
  2. esanchezfo

    Segmentation fault char array pointer

    esanchezfo, Jun 1, 2006, in forum: C Programming
    Replies:
    1
    Views:
    434
    Fred Kleinschmidt
    Jun 1, 2006
  3. Ben
    Replies:
    8
    Views:
    457
  4. Replies:
    1
    Views:
    413
  5. Replies:
    3
    Views:
    965
    sturlamolden
    Mar 31, 2008
Loading...

Share This Page