Reputation: 1779
This is a function that i've written:
uint32_t file_list(char *path, char ***ls){
DIR *dp;
//uint32_t i;
struct stat fileStat;
struct dirent *ep = NULL;
uint32_t len, count = 0;
int file = 0;
*ls = NULL;
dp = opendir (path);
if(dp == NULL){
fprintf(stderr, "no dir: %s\n", path);
exit(1);
}
ep = readdir(dp);
while(NULL != ep){
count++;
ep = readdir(dp);
}
rewinddir(dp);
*ls = calloc(count, sizeof(char *));
count = 0;
ep = readdir(dp);
while(ep != NULL){
if((file = open(ep->d_name, O_RDONLY)) < 0){
perror("apertura file");
exit(1);
}
if(fstat(file, &fileStat) != 0){
perror("filestat");
free(*ls);
close(file);
exit(EXIT_FAILURE);
}
close(file);
if(S_ISDIR(fileStat.st_mode)){
len = strlen(ep->d_name);
(*ls)[count] = malloc(len+5); /* lunghezza stringa + "DIR \n" */
strcpy((*ls)[count], "DIR "); /* copio DIR */
strcat((*ls)[count++], ep->d_name); /* concateno la stringa DIR con il nome della dir */
ep = readdir(dp);
}
else{
(*ls)[count++] = strdup(ep->d_name);
ep = readdir(dp);
}
}
/*for(i=0; i<count; i++){
free((*ls)[count]);
}*/
(void)closedir(dp);
return count;
}
into the main program i have char **files
and then the part where i get the count is count = file_list("./", &files);
What is my problem?
Everbody know that the dynamically allocated memory they (the pointers) might refer to, must be freed but if i free the pointers (with the for loop) then into the main program i got an unexpected behaviour during the file list (duplicate file name, no file name, etc).
In fact if i don't free the pointers all work perfectly.
So my question is: how to free these pointers?
Thanks in advance!
Upvotes: 0
Views: 181
Reputation: 1639
For starters, your ls parameter is a char***
, so if that's what you were going for, you need to have an inner loop to free up all of the inner pointers (**ls
) before freeing up each of the other ones (*ls
). If you only want double indirection on ls
, then get rid of one of the *s in your parameter declaration.
(BTW, you needn't use array notation in your loop to free up the pointers (or anywhere else that you access the allocated elements in ls
). free(*(ls + count));
is usually the more accepted idiom. Pointer arithmetic works regardless of what the data type is (other than void
), because the compiler takes that into account.)
Upvotes: 1
Reputation: 67745
Everbody know that the pointers must be freed but if i free the pointers (with the for loop) then into the main program i got an unexpected behaviour during the file list (duplicate file name, no file name, etc).
Your problem is that you allocate and free in the same function, which render your function basically useless (if I understand correctly anyway). If you free in the same function, after it returns (i.e.: in the "main program"), you end up accessing memory segments that have been released to the operating system, which is undefined behavior.
You'd need two functions, one for the allocation (the one above), and one to free it once you're done, per example:
char** files;
uint32_t count = file_list("./", &files);
// do something with files here
file_list_free(&files, count);
Keep in mind that your free function will need to know the count
to prevent a buffer overrun.
There are other problems with your code (e.g.: not checking the return value of calloc
, etc.), but it would be too long to cover them all here (and don't necessarily relate to your actual question).
Upvotes: 2
Reputation: 2141
You have to define an extra function, so the caller can free the data when it is done using it:
void free_file_list(char ***ls, int count) {
for(int i=0; i<count; i++){
free((*ls)[i]);
}
free(*ls);
}
Your documentation then must explain that each call to file_list
must be matched with a call to free_file_list
.
I would store count
in a struct like this, though:
struct {
char ***ls;
int count;
} FILE_LIST;
Upvotes: 1
Reputation: 157484
Free the pointers in the main program, after you've finished using them.
You need to free *ls
as well (again, after you've finished with it).
Upvotes: 0