I need to dynamically populate an array of strings in C. Here is the example of my code. Compiles fine, segmentation faults. Is it possible to achieve this functionality?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_FILE_NAME_LENGTH 255
void loadList(char*** files,int *filesSize);
int main (int argc, char *argv[])
{
char** files;
int filesSize=-1;
loadList(&files, &filesSize);
//printf("filesize= %d\n",filesSize );
for(int i=0;i< filesSize;i++) printf("%s\n", files[i]);
free(files);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
void loadList(char*** files,int *filesSize){
*filesSize=3;
//some arry for the example
char *values[] = {"100.dat", "150.dat", "200.dat"};
for(int i=0;i< *filesSize;i++){
*files=(char**) realloc(*files,(i+1) * sizeof(**files));
*files[i]=malloc((MAX_FILE_NAME_LENGTH+1) * sizeof(char*));
strcpy(*files[i],values[i]);
printf("%s\n", files[i]);
}
}
In *files = (char **)realloc(*files, (i + 1) * sizeof(**files));
you rely on *files
to point at already allocated memory or NULL
. Neither is true.
*files[i]
should also be (*files)[i]
because of operator precedence.
You also forgot to free
the allocations made inside the loop. A fix could look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_FILE_NAME_LENGTH 255
void loadList(char ***files, size_t *filesSize) {
// some array for the example
const char *values[] = {"100.dat", "150.dat", "200.dat"};
*filesSize = sizeof values / sizeof *values;
*files = NULL; // crucial for first realloc
for (int i = 0; i < *filesSize; i++) {
*files = realloc(*files, (i+1) * sizeof **files);
// I'm using strlen here instead of MAX_FILE_NAME_LENGTH but
// you can change that back if you want more space than the
// strings really need.
(*files)[i] = malloc((strlen(values[i]) + 1) * sizeof(char));
strcpy((*files)[i], values[i]);
}
}
int main(int argc, char *argv[]) {
char **files;
size_t filesSize = -1;
loadList(&files, &filesSize);
// printf("filesize= %d\n",filesSize );
for (int i = 0; i < filesSize; i++) printf("%s\n", files[i]);
// free what was allocated in the loop
for (int i = 0; i < filesSize; i++) free(files[i]);
free(files);
return 0;
}
One note on files = realloc(*files, ...
though:
If realloc
fails you've lost the original pointer and will not be able to recover. Either assign the return value to a temporary variable and check that it worked or return from the function (after setting *filesSize
to i
) or exit the program if *files == NULL
.