Как исправить ошибку сегментации при использовании struct dirent в C

Мой код печатает имена файлов/каталогов по заданному пути (пользователь вводит его как аргумент командной строки). При выполнении с заданным путем в каталоге он просто работает нормально, но предполагается, что он будет делать то же самое для текущего рабочего каталога, если пользователь не предоставляет аргумент командной строки.

У меня возникает ошибка сегментации, если я просто запускаю как: ./a.out
Это работает, когда я запускаю как: ./a.out /path

Пожалуйста, исправьте мой код, предоставив необходимый фрагмент кода

Я попытался выполнить отладку и обнаружил, что она выдает ошибку сразу после выполнения строки, следующей за строкой в ​​функции depthFirst.

printf("%s\n", sd->d_name);

Мой ошибочный код:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <limits.h>
void depthFirst(char * path){
        struct dirent *sd;
        DIR *dir;
        //char path[PATH_MAX];

        dir = opendir(path);


                if(dir == NULL){
                        printf("Error, unable to open\n");
                        exit(1);
                }

                while( (sd = readdir(dir)) != NULL){
                        if(strcmp(sd->d_name, ".") != 0 && strcmp(sd->d_name, "..") != 0){
                        printf("%s\n", sd->d_name);
                        realpath(sd->d_name,path);
                        if(isdirectory(path)){
                                printf("\t");
                                depthFirst(sd->d_name);

                        }
                }

                }


        closedir(dir);
}

int isdirectory(char *path) {
   struct stat statbuf;
   if (stat(path, &statbuf) == -1)
      return 0;
   else
      return S_ISDIR(statbuf.st_mode);
}

int main(int argc, char *argv[]){
        char * path;
        char * currentDirectory;

        if(argc<2){
                currentDirectory = ".";
                depthFirst(currentDirectory);
        }
        else{
                path = argv[1];
                depthFirst(path);

        }
        return 0;
}

Результат показан ниже:

.git
Segmentation fault

person omer muhit    schedule 11.09.2019    source источник
comment
Почему вы называете realpath по имени записи каталога? Это просто компонент пути. И можно ли использовать ввод path в качестве целевого буфера в вызове realpath? В main вы передаете строковый литерал как path в depthFirst; изменение строковых литералов является неопределенным поведением.   -  person Kaz    schedule 11.09.2019


Ответы (1)


Джонатан опередил меня в комментариях, но это изменение решило проблему.

@@ -9,7 +9,7 @@
 void depthFirst(char * path){
         struct dirent *sd;
         DIR *dir;
-        //char path[PATH_MAX];
+        char rpath[PATH_MAX];

         dir = opendir(path);

@@ -22,8 +22,8 @@
                 while( (sd = readdir(dir)) != NULL){
                         if(strcmp(sd->d_name, ".") != 0 && strcmp(sd->d_name, "..") != 0){
                         printf("%s\n", sd->d_name);
-                        realpath(sd->d_name,path);
-                        if(isdirectory(path)){
+                        realpath(sd->d_name,rpath);
+                        if(isdirectory(rpath)){
                                 printf("\t");
                                 depthFirst(sd->d_name);

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

person mpontillo    schedule 11.09.2019