开发者

In C, modify the target of a pointer to an array of pointers when passed as argument to a function

开发者 https://www.devze.com 2023-04-04 04:36 出处:网络
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 seg

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().

0

精彩评论

暂无评论...
验证码 换一张
取 消