В C измените цель указателя на массив указателей при передаче в качестве аргумента функции - PullRequest
1 голос
/ 11 сентября 2011

Мне нужна функция, которая возвращает содержимое данного каталога.Для этого я использую scandir из dirent.h.Приведенный ниже код успешно компилируется (gcc -Wall test.c), но последний printf приводит к ошибке сегментации.Это означает, что структура "eps" (указатель на массив указателей на структуры dirent) все еще пуста после функции: как я могу это исправить?

#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;
  struct dirent ** eps = NULL;
  status = list_dir("/home", eps);
  if (status)
  {
    puts("ok");
    printf("outside function: %s\n", eps[0]->d_name);
  }
  return EXIT_SUCCESS;
}

Ответы [ 3 ]

1 голос
/ 11 сентября 2011

Поскольку ваш указатель изменился, и вы смотрите не на ту вещь в main():)

Вы передаете указатель на указатель на указатель на scandir(). это меняет то, на что указывает указатель на указатель (я знаю, что больно читать ...).

Поскольку вы вызываете scandir() с &eps в своей функции, вы теряете это изменение вне функции. Значение eps изменилось внутри вашей функции.

Чтобы лучше понять это, в текущей функции оберните вызов scandir() операторами printf(), показывающими, каково значение, содержащееся в eps:

...
printf("%p\n", eps);
int nbfiles = scandir(dirname, &eps, myselector, alphasort);
printf("%p\n", eps);
...

Чтобы исправить это, измените вашу функцию на:

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;
}

И назовите это как ...

status = list_dir("/home", &eps);

в main(). Тогда он будет отлично работать:

broach @ roach-VirtualBox: ~ $ ./test
внутренняя функция: протяжка
ОК
внешняя функция: протяжка

1 голос
/ 11 сентября 2011

Заставьте list_dir принимать struct dirent *** вместо struct dirent **, избавьтесь от оператора & в вызове scandir () и добавьте его в вызов list_dir () из main.Первые строки list_dir () становятся:

int list_dir(char * dirname, struct dirent *** eps)
{
  int nbfiles = scandir(dirname, eps, myselector, alphasort);

, а вызов list_dir () в main становится:

status = list_dir("/home", &eps);

Таким образом list_dir () может позволить scandir () изменять eps из main () через его адрес, вместо изменения аргумента в стеке, переданного list_dir ().

1 голос
/ 11 сентября 2011

Похоже, вы не рассматриваете случай, когда scandir возвращает 0, т. Е. Пустой каталог. Возвращаемое значение -1 только для ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...