深度优先第一个目录遍历导致C中的分段错误

时间:2012-12-15 15:33:01

标签: c unix directory depth-first-search

我正在编写一个代码,使用depth first算法遍历目录。问题是程序没有显示任何内容并给出Segmentation Fault error。我试图调试它,但它仍然没有价值,因为我还在学习东西。所以现在我需要专家的帮助。这是代码:

void func(char path[]);

int main(int argc, char *argv) {
    char buf[255];

    scanf("%s",buf);
    func(buf);
    return 0;
}

void func(char path[]) {
    DIR *dirp;
    struct stat states;
    struct dirent *direntp;
    printf("Inside\n");
    dirp=opendir(path);
    stat(path, &states);

    while ((direntp=readdir(dirp)) != NULL) {
        if (S_ISDIR(states.st_mode)) {
            printf("Calling Func\n");
            func(direntp->d_name);
            chdir("..");
        } else if (!S_ISDIR(states.st_mode)) {
            printf("  %s\n", direntp->d_name);
        } else if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) {
            continue;
        }
    }
    return ;
}

2 个答案:

答案 0 :(得分:1)

在func里面,在前面,把那个:

dirp=opendir (path);
if (!dirp)
  return;

和顺便说一下,int main (int argc, char *argv[])

答案 1 :(得分:0)

要进行调试打印,请打印到stderr;它是行缓冲的,因此看起来更可靠。

您的功能概括为:

void func(char path[])
{
    DIR *dirp;
    struct stat states;
    struct dirent *direntp;
    printf("Inside\n");
    dirp=opendir(path);
    stat(path,&states);

    while ((direntp = readdir(dirp)) != NULL)
    {
        if (S_ISDIR(states.st_mode))
        {
            printf("Calling Func\n");
            func(direntp->d_name);
            chdir("..");
        }
        else if (!S_ISDIR(states.st_mode))
        {
            printf("  %s\n",direntp->d_name);
        }
        else if (!strcmp(direntp->d_name,".") || !strcmp(direntp->d_name,".."))
        {
            continue;
        }
    }
}

chdir("..")是不明智的;你既没有对相关目录做chdir()也没有确保目录是当前目录的直接子目录,这意味着这个代码将变得混乱...如果它到达那个位

您执行stat(path, &states);但不检查它是否有效。

您执行dirp = opendir(path);但不检查它是否有效。

您不会在每个条目上执行stat();你不断使用path的初始统计数据。这可能是你测试时的一个目录,所以你然后递归调用该函数,这将是一个目录读取.,如果你没有用完,你可能最终会耗尽堆栈首先是DIR指针。

你在循环中的测试是错误排序的,即使你安排了stat()文件 - 这是一个非常重要的操作,因为你刚读过的名字必须附加到目录的路径上才能形成正确的文件名。您的代码是:

if (is a directory)
else if (is not a directory)
else if (name is . or ..)
else ...missing...

首先,if和以下else if涵盖了所有选项,因此名称test和final(不存在的)else将永远不会被执行。您可能首先需要名称test(伪代码):

if (name is a "." or "..")
    print "Skipping";
else if (name is a directory)
{
    create "path/name" as string;
    recurse with "path/name";
}
else
    print "Skipping non-directory";

请注意,这始终会在每次迭代中打印一些内容。在调试时这非常重要。当你做了一些你不期望的事情时,你不希望代码保持安静。

请注意,您不要拨打closedir();这意味着你将耗尽目录描述符,在dirp中获得一个NULL值,当你使用它时崩溃。

请注意,伪代码不包含任何chdir()操作。使用它们非常非常谨慎。了解fchdir()

的使用

阅读ftw()nftw();关于这些功能面临的复杂情况,有一些注意事项。