c/c++语言开发共享Strdup返回的地址超出范围

在我花了更多时间之前,我想我会问。 Valgrind没有报告任何事情,事实上它并没有与Valgrind一起崩溃。

char* a = "HI"; char* b = strdup(a); 

(gdb)print b => $8 = 0xffffffffe8003680

这只发生在我动态加载的共享库中(用dlopen加载)。 我不知道什么可能导致这种情况。 我剥离了该库中的所有内容,其中只有这两行。 你能帮我调试一下吗?

如果我现在尝试访问b

 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6 

这可能会出错?

回溯:

 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6 (gdb) bt #0 0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6 #1 0x00007ffff767088a in vfprintf () from /lib64/libc.so.6 #2 0x00007ffff767af79 in printf () from /lib64/libc.so.6 #3 0x00007ffff722678c in _mkp_stage_30 (plugin=0x61f420, cs=0x7fffe8002040, sr=0x7fffe8003070) at hello.c:68 #4 0x000000000040f93a in mk_plugin_stage_run (hook=16, socket=18, conx=0x0, cs=0x7fffe8002040, sr=0x7fffe8003070) at mk_plugin.c:558 #5 0x000000000040c501 in mk_http_init (cs=0x7fffe8002040, sr=0x7fffe8003070) at mk_http.c:255 #6 0x0000000000404870 in mk_request_process (cs=0x7fffe8002040, sr=0x7fffe8003070) at mk_request.c:510 #7 0x0000000000404d75 in mk_handler_write (socket=18, cs=0x7fffe8002040) at mk_request.c:630 #8 0x000000000040b446 in mk_conn_write (socket=18) at mk_connection.c:130 #9 0x0000000000409352 in mk_epoll_init (efd=12, handler=0x7fffe8001690, max_events=202) at mk_epoll.c:102 #10 0x0000000000409b4e in mk_sched_launch_worker_loop (thread_conf=0x61a5a0) at mk_scheduler.c:196 #11 0x00007ffff79c2f05 in start_thread () from /lib64/libpthread.so.0 #12 0x00007ffff770553d in clone () from /lib64/libc.so.6 

    你需要添加

     #include  

    得到strdup()的声明。

    或者,如果您已经拥有它,则需要以使strdup()可见的方式调用编译器(有关详细信息,请参见下文)。 strdup()由POSIX定义,而不是由ISO C定义。

    gcc默认启用相应的宏,但使用-ansi-std=c99将禁用它们。 您还可以在源文件的顶部添加适当的#define

    在没有可见声明的情况下,编译器假定(根据C90规则) strdup()返回int 。 这会导致未定义的行为。 特别是,如果int是32位而char*是64位,那么Bad Things将会发生。 (根据C99规则,调用没有可见声明的函数是违反约束的。)

    您还应该提高编译器的警告级别并注意警告 。 这样的问题应该在编译时出现; 您不应该诊断运行时行为。

    更新:

    以下是基于我自己的Ubuntu 11.04系统的文档和实验。 它可能适用于任何使用glibc的系统; 其中一些可能适用于非glibc系统。 man strdupman feature_test_macros获取更多信息。

    要使用strdup()必须使用#include 才能使声明可见。 (如果省略这个,编译器不一定会抱怨,但无论如何你都需要它。)

    此外,您需要在#include 之前使用以下(或等效的)之一:

     #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使用-ansi-std=...选项(或者使用clang的等价物); gcc默认启用其中一些宏。

    如果你想用-ansistd=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()可见。)

    由于strdup()是一个如此简单的函数,您可以考虑在标准ISO C中编写自己的实现并使用它。 例如(请注意,以str开头的名称是保留的):

     char *dupstr(const char *s) { char *const result = malloc(strlen(s) + 1); if (result != NULL) { strcpy(result, s); } return result; } 

    (我只对其进行了最低限度的测试。)如果strdup()是您正在使用的唯一POSIX特定function,那么滚动自己可能是最好的解决方案。 如果你正在使用其他特定于POSIX的函数,那么无论如何你都必须处理所有这些东西,你也可以使用strdup()本身。

    看起来你错误地调用了printf()。 而不是printf(b),你需要做:

     printf("%sn", b); 

    编辑:在上面添加 n,感谢Jonathan。

      以上就是c/c++开发分享Strdup返回的地址超出范围相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/560023.html

      (0)
      上一篇 2021年1月27日
      下一篇 2021年1月27日

      精彩推荐