尝试获取文件名长度时出现分段错误

时间:2015-12-07 20:47:16

标签: c

我已将分段错误缩小到导致它的特定代码行。这是一个直截了当的例子,显示了我遇到的问题。

int main()
{
    char** files;
    int sum;
    int i;

    DIR *d;
    struct dirent *dir;
    d = opendir(".");
    if (d)
    {
            sum = file_sum();
            char* files[sum];
            i = 0;

            while ((dir = readdir(d)) != NULL)
            {
                    files[i] = dir->d_name;
                    i++;
            }

            closedir(d);
    }
    else
    {
            return -1;
    }

    int len = strlen(files[0]);    /*segmentation fault here*/

    return 0;
}

基本上,程序正在做的是从当前目录中获取所有文件的名称并将它们放入数组中。然后我将尝试获取所有文件名的大小,但我遇到了分段错误。我的理论是,文件名可能不是以空值终止的吗?如果这是真的,我不确定是否有解决办法,但我们非常感谢您的帮助。

由于

编辑:抱歉,我在这里遇到了错误。只有在我尝试存储strlen返回值时才会发生分段错误,因为我现在已将代码更改为

2 个答案:

答案 0 :(得分:4)

if块内,您正在定义名为files的变量。这将屏蔽函数顶部的同名变量。它是 not 在更高的范围内指定数组的大小,这似乎是你的意图。因此,当您退出if块时,内部files超出范围,外部files保持未初始化状态。然后取消引用未初始化的指针,导致核心转储。

您要做的是在if块内为您需要的内存动态分配必要的内存。

此外,检索到dir->d_name的目录名可能会在每次调用readdir时被覆盖,因此您也需要为此分配空间。

编辑:

您也不需要单独的功能来获取文件数。您可以使用默认大小和realloc分配数组,以根据需要进行扩展:

int main()
{
    char** files;
    int sum;
    int i;

    DIR *d;
    struct dirent *dir;
    d = opendir(".");
    if (d)
    {
            int size = 10;
            sum = 0;
            files = malloc(size * sizeof(char *));   // allocate the array
            if (files == NULL) {
                perror("malloc failed");
                exit(1);
            }

            while ((dir = readdir(d)) != NULL)
            {
                    if (sum >= size) {
                        // if the array is full, realloc twice the size
                        char **tmp;
                        size *= 2;
                        tmp = realloc(size * sizeof(char *));
                        if (tmp == NULL) {
                            perror("realloc failed");
                            exit(1);
                        }
                        files = tmp;
                    }
                    files[sum] = strdup(dir->d_name);   // allocate and copy each string
                    sum++;
            }

            closedir(d);
    }
    else
    {
            return -1;
    }

    strlen(files[0]);

    // free the individual strings
    for (i=0; i<sum; i++) {
        free(files[i]);
    }
    // free the array
    free(files);

    return 0;
}

答案 1 :(得分:0)

使用“char * files [sum]”只在2条条件下才是安全的:

  • 在声明范围结束后你没有尝试访问数组:在声明它的“if”结尾之后你不应该尝试访问“files”数组

  • 需要安全保留char *目标。假设目标在dir-&gt; d_name之后有效,但在关闭d DIR之后它是非常有风险的

  • 是合理的。

如果您知道目录中可以有多少文件,这是一个简单的修复:将dirent结构复制到dirList是最简单的,但它是一个非常大的结构。您也可以使用“dirListPtr”仅复制指向dirent的指针,但您需要确保您的dirent结构仍然有效。这就是为什么我把“封闭”放得更远了。

如果您不确定文件的数量,可以采用动态分配(参见dbush answer)。如果要在另一个函数中使用数据,也需要分配。

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>

int main()
{
    int sum;
    int i;

    DIR *d;
    struct dirent* dir;
    // you must be sure to have less than 255 files
    struct dirent dirList[255];
    struct dirent* dirListPtr[255];
    d = opendir(".");
    if (d)
    {

            i = 0;

            while ((dir = readdir(d)) != NULL)
            {
                    // copy the dirent information to our local variable which will live until the end of the main
                    dirList[i] = *dir;
                    // or keep only a pointer to the dirent struct: the system will surely not discard the dirent at least as long as d is open
                    dirListPtr[i] = dir;
                    i++;
            }

    }
    else
    {
            return -1;
    }

    printf("size of filename: %lu size of dirent %lu\n", strlen(dirList[0].d_name), sizeof(dirList[0]));
    printf("size of filename: %lu\n", strlen(dirListPtr[0]->d_name));

closedir(d);

    return 0;
}

文件名大小:2大小为dirent 280

文件名大小:2