C 为什么string.h函数会出现segfaults?

C 为什么string.h函数会出现segfaults?,c,C,在我同事的电脑中使用相同的命令,我的程序可以正常工作。 但在我的电脑里,程序会因为segfault而崩溃 核心的GDB回溯如下所示: #0 strrchr () at ../sysdeps/x86_64/strrchr.S:32 32 ../sysdeps/x86_64/strrchr.S: no such file or directory (gdb) bt #0 strrchr () at ../sysdeps/x86_64/strrchr.S:32 #1 0x00007f10961

在我同事的电脑中使用相同的命令,我的程序可以正常工作。 但在我的电脑里,程序会因为segfault而崩溃

核心的GDB回溯如下所示:

#0 strrchr () at ../sysdeps/x86_64/strrchr.S:32
32     ../sysdeps/x86_64/strrchr.S: no such file or directory
(gdb) bt
#0 strrchr () at ../sysdeps/x86_64/strrchr.S:32
#1 0x00007f10961236d7 in dirname (path=0x324a47a0 <error: Cannot access memory at address 0x324a47a0>) at dirname.c:31
其中get_abs_name定义为

char* get_abs_name(char* dir) {
    char abs_path[PATH_MAX];
    char* c = malloc(PATH_MAX*sizeof(char));
    realpath(dir, abs_path);
    strcpy(c, abs_path);
    return c;
}
+Edit2:“dir”是特定文件的路径,如“../program/blablabla.jpg”

使用valgrind

printf("%s\n", dir)
通常打印“/home/frozenca/path\u to\u program”。 我猜不出为什么程序在没有valgrind的情况下崩溃。

转换类型

char* c = malloc(PATH_MAX*sizeof(char));
谢谢

转换类型

char* c = malloc(PATH_MAX*sizeof(char));

谢谢

完全删除函数并使用返回值
realpath(dir,NULL)

完全删除函数并使用返回值
realpath(dir,NULL)

如果没有。除了不检查错误之外,您的代码看起来基本正确(尽管复杂)

char* get_abs_name(char* dir) {
    char abs_path[PATH_MAX];
    char* c = malloc(PATH_MAX*sizeof(char));  /* this may return NULL */
    realpath(dir, abs_path);                  /* this may return NULL */
    strcpy(c, abs_path);
    return c;
}
现在,这怎么会导致你看到的错误呢?那么,如果
malloc
返回NULL,您将在
strcpy
中立即得到一个崩溃。但是如果
realpath
失败:

  • abs\u path
    的内容仍未定义
  • 因此
    strcpy(c,abs\u路径)
    将复制未定义的内容。如果
    abs\u path[0]
    恰好是
    \0
    ,这可能导致它只复制一个字节。但也可能导致大量堆损坏。这取决于不相关的条件,例如程序的编译方式,以及是否附加了valgrind等调试工具
TL;DR:养成检查每个可能失败的功能的习惯

char* get_abs_name(char* dir) {
    char abs_path[PATH_MAX];
    char* c = malloc(PATH_MAX*sizeof(char));
    if (!c) { return NULL; }
    if (!realpath(dir, abs_path)) {
        free(c);
        return NULL;
    }
    strcpy(c, abs_path);
    return c;
}
或者,在这里,假设GNU系统或POSIX.1-2008系统,您可以将其简化很多:

char * get_abs_name(const char * dir) {
    return realpath(dir, NULL);
}

但是请注意,无论哪种方式,在主程序中,您也必须检查
get\u abs\u name()
是否未返回NULL,否则
dirname()
将崩溃。

如果没有。除了不检查错误之外,您的代码看起来基本正确(尽管复杂)

char* get_abs_name(char* dir) {
    char abs_path[PATH_MAX];
    char* c = malloc(PATH_MAX*sizeof(char));  /* this may return NULL */
    realpath(dir, abs_path);                  /* this may return NULL */
    strcpy(c, abs_path);
    return c;
}
现在,这怎么会导致你看到的错误呢?那么,如果
malloc
返回NULL,您将在
strcpy
中立即得到一个崩溃。但是如果
realpath
失败:

  • abs\u path
    的内容仍未定义
  • 因此
    strcpy(c,abs\u路径)
    将复制未定义的内容。如果
    abs\u path[0]
    恰好是
    \0
    ,这可能导致它只复制一个字节。但也可能导致大量堆损坏。这取决于不相关的条件,例如程序的编译方式,以及是否附加了valgrind等调试工具
TL;DR:养成检查每个可能失败的功能的习惯

char* get_abs_name(char* dir) {
    char abs_path[PATH_MAX];
    char* c = malloc(PATH_MAX*sizeof(char));
    if (!c) { return NULL; }
    if (!realpath(dir, abs_path)) {
        free(c);
        return NULL;
    }
    strcpy(c, abs_path);
    return c;
}
或者,在这里,假设GNU系统或POSIX.1-2008系统,您可以将其简化很多:

char * get_abs_name(const char * dir) {
    return realpath(dir, NULL);
}

但是请注意,无论哪种方式,在主程序中,您也必须检查
get\u abs\u name()
是否未返回NULL,否则
dirname()
将崩溃。

您的程序中存在错误。很可能是缓冲区溢出。发布代码以获得有用的答案。因此,您希望我们在不查看代码的情况下修复您的代码。嗯。请学习a的概念并阅读。错误发生在strhr/strcmp/strlen/etc中。不是因为这些函数上有错误,而是因为您自己的代码以您不希望的方式调用这些函数(直接或间接)。您需要检查realpath()是否成功-因为您没有在此处检查错误,可能还有其他重要的地方您忘记了检查并捕获了真正的错误。您还需要检查函数的
dir
参数,以验证它是否包含您认为它应该包含的内容(并向我们展示它包含的内容)。@spectras我正要编辑我的注释以包含该信息:),因此该函数基本上是
realpath
的包装器,并且是无用的(和有缺陷的).您的程序中有一个错误。很可能是缓冲区溢出。发布代码以获得有用的答案。因此,您希望我们在不查看代码的情况下修复您的代码。嗯。请学习a的概念并阅读。错误发生在strhr/strcmp/strlen/etc中。不是因为这些函数上有错误,而是因为您自己的代码以您不希望的方式调用这些函数(直接或间接)。您需要检查realpath()是否成功-因为您没有在此处检查错误,可能还有其他重要的地方您忘记了检查并捕获了真正的错误。您还需要检查函数的
dir
参数,以验证它是否包含您认为它应该包含的内容(并向我们展示它包含的内容)。@spectras我正要编辑我的注释以包含该信息:),因此该函数基本上是
realpath
的包装,并且是无用的(而且有缺陷的)。