Как правильно использовать scandir () в c?

Я пытаюсь сохранить список файлов в переменной char **.

scandir () правильно завершается, но при попытке распечатать символ ** возникает segmentation fault.

Вот код:

int main() { char** fileList; int noOfFiles; char* path = "."; makeList(&fileList, &noOfFiles, path); return 0; } void makeList(char ***fileList, int* noOfFiles, char* path){ struct dirent **fileListTemp; *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort); int i; fileList = (char***)malloc(sizeof(char***)); *fileList = (char**)malloc(*noOfFiles * sizeof(char*)); printf("total: %d files\n",*noOfFiles); for(i = 0; i  d_name) *sizeof(char)); strcpy(*fileList[i], fileListTemp[i] -> d_name); printf("%s\n",*fileList[i]); } return; } 

Это дает ошибку сегментации после печати 2 имен файлов.

выход:

всего: 27 файлов.

..

.jv

Ошибка сегментации (сброс ядра)

Функция scandir() выделяет вам память.

Вам не нужно выделять ЛЮБУЮ память. Вам нужно освободить память, возвращенную вам scandir() .

Ваши кодовые вызовы: *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);

При возврате noOfFiles будет содержать количество записей в каталоге каталога path , а fileListTemp укажет на выделенный массив указателей на выделенные строки, каждый из которых указывает на выделенный блок, содержащий нулевое завершенное имя файла.

Если ваш каталог содержит файлы «FirstFile.txt», «AnotherFile.txt», «ThirdFile.txt», например, с вашим вызовом, по возвращении из scandir() , noOfFiles будет установлен на 5 для трех файлов плюс два больше для “.” и “..”. ЗАПИСИ НЕ ЗАКАЗЫВАЮТСЯ, ЕСЛИ ВЫ НЕ ПРОПУСТИТЕ «альфа-сортировку». (На самом деле это немного некорректно. Они будут в порядке имен файлов каталога, которые зависят от порядка, в котором файлы были изначально созданы.)

Поскольку вы передали «alphasort», вы должны увидеть записи в следующем порядке (я явно показываю нуль-байтовую строку-терминатор:

 fileListTemp[0] == ".\0" fileListTemp[1] == "..\0" fileListTemp[2] == "AnotherFile.txt\0" fileListTemp[3] == "FirstFile.txt\0" fileListTemp[4] == "ThirdFile.txt\0" 

Поэтому fileListTemp указывает на блок выделенной памяти, содержащий пять указателей (char *). Каждый из пяти указателей (char *) указывает на блок выделенной памяти, содержащий имя записи каталога с нулевым завершением.

Это SIX блоков выделенной памяти.

Вы можете использовать эту выделенную память, пока не закончите с ней, и затем вы вызываете free () на запись EACH в массиве, за которой следует free () самого массива.

Вы ДОЛЖНЫ освобождать каждую запись, а также массив. Все они независимо выделяют капли памяти.

Когда вы закончите со списком, вы должны:

 for (int i = 0; i < noOfFiles; i++) { free(fileListTemp[i]; } free(fileListTemp); 

Это старый вопрос, но так как я натолкнулся на него, и он не разрешил мой вопрос так же эффективно, как на странице man, я копирую fragment кода с man- страницы в качестве нового ответа на будущее.

  #include  int main(void) { struct dirent **namelist; int n; n = scandir(".", &namelist, NULL, alphasort); if (n < 0) perror("scandir"); else { while (n--) { printf("%s\n", namelist[n]->d_name); free(namelist[n]); } free(namelist); } } 

Я не уверен, что это проблема, но вам нужно выделить еще один байт для нулевого завершения:

 *fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name + 1) *sizeof(char));