C Strdup返回地址超出范围

C Strdup返回地址超出范围,c,C,我想在花更多时间做这件事之前我应该先问一下。Valgrind没有报告任何事情,事实上它没有与Valgrind崩溃 char* a = "HI"; char* b = strdup(a); (gdb)打印b=> $8=0xFFFFFFFF8003680 这只发生在动态加载的共享库(使用dlopen加载)中。我不知道这可能是什么原因。我几乎把图书馆里的所有东西都去掉了,里面只有这两行。你能帮我调试一下吗 如果我现在尝试访问b: Program received signal SIGSEGV, Se

我想在花更多时间做这件事之前我应该先问一下。Valgrind没有报告任何事情,事实上它没有与Valgrind崩溃

char* a = "HI";
char* b = strdup(a);
(gdb)打印b=>

$8=0xFFFFFFFF8003680

这只发生在动态加载的共享库(使用dlopen加载)中。我不知道这可能是什么原因。我几乎把图书馆里的所有东西都去掉了,里面只有这两行。你能帮我调试一下吗

如果我现在尝试访问
b

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6
这里可能出了什么问题

回溯:


看起来您没有正确调用printf()。您需要执行以下操作,而不是printf(b):

printf("%s\n", b);
编辑:由于Jonathan,在上面添加了\n。

您需要添加

#include <string.h>




做到这一点的最简单方法就是不使用gcc的
-ansi
-std=…
选项(或clang的等效选项);默认情况下,gcc启用其中一些宏

如果要使用
-ansi
std=c99
进行编译,则可以显式设置上述宏中的一个(如果使用第四个选项,则可以设置两个),或者在源代码中使用显式的
#define
(可能是最好的解决方案),或者使用,例如
gcc-std=c99-D_XOPEN#source=500

正如我前面提到的,您应该在编译器上启动警告级别。对于gcc,我通常使用:

gcc -std=c99 -pedantic -Wall -Wextra -O3
-O3
启用优化;一个副作用是,它支持执行这些优化所需的分析,这可以检测到许多在较低优化级别上不明显的问题

所有这些繁琐的原因是,
strdup()
不是由ANSI/ISO C标准定义的(委员会选择不包括它),而是由POSIX定义的——它的声明在ISO C标准标题之一的
中。在严格符合ISO C的模式下,名称
strdup()
可能无法在
中显示。您必须采取这些额外的步骤来告诉编译器使其可见。(默认情况下,gcc不是完全一致的C编译器,这就是为什么它能够在默认情况下使
strdup()
可见。)

<> > <代码> StrudUp()/Case>是这样一个简单的函数,您可以考虑只在标准ISO C中编写自己的实现,并使用该实现。例如(请注意,以
str
开头的名称是保留的):


(我只做了最低限度的测试。)如果
strdup()
是您正在使用的唯一特定于POSIX的函数,那么滚动您自己的函数可能是最好的解决方案。如果您使用的是其他POSIX特定的函数,那么您将不得不处理所有这些内容,您还可以使用
strdup()
本身。

在SIGSEGV之后,您能在gdb中获得回溯(即运行bt)并显示输出吗?@DanFego好的,我添加了它。@Blub:您能发布您的实际代码吗(也许将其缩短到最短,这仍然是问题所在)?我有一种强烈的感觉,代码中还有其他一些东西我们还没有显示。您显示给我们的地址看起来很奇怪,好像在返回
strdup
时发生了32/64位冲突。如果clang抱怨您的include肯定有什么可疑的地方。也许有些文件定义了include guar其他文件或类似文件的ds。您得到并忽略了哪些编译器警告?您要求的是哪些警告?特别是,是否声明了
strdup()
?如果不是,编译器将假定它返回一个整数(4字节)然后扩展它来创建指针,而不是将所有返回的8个字节都作为指针处理。为了适度确保看到结果,该格式需要是
%s\n“
甚至
“b=\n”
。但是,对于给定的数据(“HI”),普通的
printf(b)
应该可以工作,尽管不是很安全。但这不是产生segfault的原因,不是吗?“HI”不包含任何
%
左右的内容,所以应该打印出来。也许这不是原因,但崩溃似乎是由printf()引起的,让函数按预期的方式调用是弄清为什么会有宏的好的第一步。嗯,也许您需要在编译过程中定义一些宏?根据我的(Linux)中文页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索主页,搜索首页,搜索外笔,搜索首页,搜索首页,搜索首页,搜索钢笔,搜索钢笔,源,以及以及以及以及以及其他来源,搜索首页,搜索首页首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索首页,搜索钢笔,搜索源码,源,搜索钢笔,源,以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及以及美国X钢笔,访问钢笔,源,源,源,源,源,源,源,源,源,源,源,源,扩展扩展扩展,源,源,源,源,源,扩展,源,扩展,扩展,扩展,扩展,扩展,扩展,扩展,扩展,扩展,扩展,扩展,扩展“检测”如果存在可用的
strdup()
,则使用它。否则使用我的onw实现。但不起作用,我在POSIX环境中,但我仍然使用我的onw实现。检查我是如何执行的:
#如果定义(_SVID_SOURCE)|定义(_BSD| u SOURCE)|定义(_xopensource)&_xopensource>=500|(_XOPEN_SOURCE)和&defined(_XOPEN_SOURCE_EXTENDED)/*此头文件中有可用的strdup()*/*包括#else char*strdup(const char*src){printf(“come src:[%s]!!\n”,src);返回memdup(&src[0],sizeof(src))}#endif
memdup()
是我复制内存块的实现。它也很简单:
void*memdup(void*src,size\u t size);
size
被传递给
malloc()
它的返回值存储在一个
void*tmp
中,该值被检查为非空值,然后
返回memcpy(tmp,src,size)
如果你的程序因为其他原因依赖POSIX,那么不管怎样,
strdup()
应该是可用的。如果不是,可能更容易无条件地使用你自己的
strdup()
类函数。(不要使用名称
strdup()
;它保留给实现。)谢谢。我将实现一个名为
strdup()
的函数。
#define _SVID_SOURCE
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500 /* or greater */
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED
#define _POSIX_C_SOURCE 200809L /* or greater */
gcc -std=c99 -pedantic -Wall -Wextra -O3
char *dupstr(const char *s) {
    char *const result = malloc(strlen(s) + 1);
    if (result != NULL) {
        strcpy(result, s);
    }
    return result;
}