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. Advertisements

  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. Advertisements

  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. Advertisements

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. jimjim
    Replies:
    16
    Views:
    1,095
    Jordan Abel
    Mar 28, 2006
  2. Chris Van Extergem

    Function pointer results in segmentation fault.

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

    Segmentation fault char array pointer

    esanchezfo, Jun 1, 2006, in forum: C Programming
    Replies:
    1
    Views:
    552
    Fred Kleinschmidt
    Jun 1, 2006
  4. Ben
    Replies:
    8
    Views:
    653
  5. Replies:
    1
    Views:
    517
  6. Replies:
    3
    Views:
    1,125
    sturlamolden
    Mar 31, 2008
  7. H.S.
    Replies:
    9
    Views:
    968
    Richard Herring
    Aug 13, 2008
  8. LL
    Replies:
    1
    Views:
    397
Loading...