I want a function that returns the content of a given directory. For this, I am using scandir
from dirent.h
. The code below compiles successfully (gcc -Wall test.c), but the last printf leads to a segmentation fault. It means that the "eps" structure (a pointer to an array of pointers to dirent structures) is still empty after the function: how can I fix this?
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
static int myselector(const struct dirent * dir_entry)
{
char * pch = strstr(dir_entry->d_name, ".");
return pch == NULL ? 1 : 0;
}
int list_dir(char * dirname, struct dirent ** eps)
{
int nbfiles = scandir(dirname, &eps, myselector, alphasort);
if(nbfiles > 0)
{
printf("inside function: %s\n", eps[0]->d_name);
return 1;
}
else
return 0;
}
int main(int argc, char *argv[])
{
int status = 0;
stru开发者_JS百科ct dirent ** eps = NULL;
status = list_dir("/home", eps);
if (status)
{
puts("ok");
printf("outside function: %s\n", eps[0]->d_name);
}
return EXIT_SUCCESS;
}
You don't seem to be covering the case where scandir
returns 0, i.e., empty directory. Return value of -1 is only for errors.
Because your pointer has changed, and you're looking at the wrong thing in main()
:)
You're passing a pointer to a pointer to a pointer to scandir()
. it's changing what the pointer to a pointer is pointing at (I know, that hurts to read ... ).
Because you're calling scandir()
with &eps
in your function, you lose that change outside of the function. The value of eps
has changed inside your function.
To better understand this, in your current function wrap the scandir()
call with printf()
statements showing you what the value contained in eps
is:
...
printf("%p\n", eps);
int nbfiles = scandir(dirname, &eps, myselector, alphasort);
printf("%p\n", eps);
...
To fix this change your function to:
int list_dir(char * dirname, struct dirent *** eps)
{
int nbfiles = scandir(dirname, eps, myselector, alphasort);
if(nbfiles != -1)
{
printf("inside function: %s\n", (*eps)[0]->d_name);
return 1;
}
else
return 0;
}
And call it as ...
status = list_dir("/home", &eps);
in main()
. It will then work perfectly:
broach@roach-VirtualBox:~$ ./test
inside function: broach
ok
outside function: broach
Make list_dir take struct dirent ***
instead of struct dirent **
, get rid of the &
operator in the scandir() call, and add it to the list_dir() call from main.
The first lines of list_dir() become:
int list_dir(char * dirname, struct dirent *** eps)
{
int nbfiles = scandir(dirname, eps, myselector, alphasort);
and the list_dir() call in main becomes:
status = list_dir("/home", &eps);
That way list_dir() can let scandir() modify eps
from main() via its address, instead of modifying the argument, on the stack, passed to list_dir().
精彩评论