Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocate a string array from inside a function in C

I have a function that scans a file and returns the number of the lines along with the lines in a string array, my function looks like this :

int load_lines(char* _file, char** _array){
    FILE *infile;
    char line_buffer[BUFSIZ];
    char line_number;

    infile = fopen(_file, "r");

    ine_number = 0;
    while (fgets(line_buffer, sizeof(line_buffer), infile)) 
        ++line_number;

    fclose(infile);
    _array = malloc (line_number * sizeof(char*));
    infile = fopen(_file, "r");
    line_number = 0;

    while (fgets(line_buffer, sizeof(line_buffer), infile)) {
        _array[line_number] = malloc(strlen(line_buffer) + 1);
        strcpy(_array[line_number], line_buffer);

        //a printf on _array[line_number] works fine here
        ++line_number;
    }

    return line_number;
}

When I call it like this:

char** _array;
line_number = load_lines(inname, _array);

_array[0];

I get a segmentation fault since the array seems to be not allocated after the return of the function.

like image 672
user824906 Avatar asked Feb 24 '23 17:02

user824906


2 Answers

When you pass an argument into a function, the function always works on a copy of that argument.

So in your case, load_lines is working on a copy of _array. The original _array is not modified:

char** _array = NULL;
printf("%p\n", _array); // Prints "0x0000"
line_number = load_lines(inname, _array);
printf("%p\n", _array); // Prints "0x0000"

To modify _array, you need to pass a pointer to it:

int load_lines(char* _file, char*** _array){
    ...
    (*array) = malloc (line_number * sizeof(char*));
    ...
    (*array)[line_number] = malloc(strlen(line_buffer) + 1);
}

char** _array = NULL;
line_number = load_lines(inname, &_array);

[However, any time you find yourself needing a triple pointer (i.e. ***), it's time to reconsider your architecture.]

like image 126
Oliver Charlesworth Avatar answered Mar 05 '23 08:03

Oliver Charlesworth


If you want to return a newly allocated array of strings from the function, then the second argument of the function must have a type of char***, eg. a pointer to an array of strings:

int load_lines(char* _file, char*** _array) {
    ...
    char** tmparray = malloc(line_number * sizeof(char*));
    ...
        tmparray[line_number] = malloc(strlen(line_buffer) + 1);
        strcpy(tmparray[line_number], line_buffer);
    ...
    (*_array) = tmparray;
}

And when you call the function:

char** _array;
line_number = load_hosts(inname, &_array);
like image 27
buc Avatar answered Mar 05 '23 07:03

buc