• strerror的坑


    最近写的一段代码,总是出core,精简了一下,稳定复现。

    #include <stdio.h>
    #include <errno.h>
    
    int main()
    {
        printf("%s
    ", strerror(errno));
        return 0;
    }
    

    编译并执行,就会报Segmentation fault (core dumped)。

    看下core的栈:

    (gdb) bt
    #0  0x0000003f0b06feb0 in strlen () from /lib64/tls/libc.so.6
    #1  0x0000003f0b0429ac in vfprintf () from /lib64/tls/libc.so.6
    #2  0x0000003f0b047f08 in printf () from /lib64/tls/libc.so.6
    #3  0x000000000040058c in main ()
    

    问题应该是出在strerror(errno)上了。

    反编译一下代码,

    0000000000400558 <main>:
      400558:       55                      push   %rbp
      400559:       48 89 e5                mov    %rsp,%rbp
      40055c:       e8 27 ff ff ff          callq  400488 <__errno_location@plt>
      400561:       8b 38                   mov    (%rax),%edi
      400563:       b8 00 00 00 00          mov    $0x0,%eax
      400568:       e8 0b ff ff ff          callq  400478 <strerror@plt>
      40056d:       89 c6                   mov    %eax,%esi                 最关键的地方:strerror返回的地址存放在eax中,eax的值赋给esi
      40056f:       bf 7c 06 40 00          mov    $0x40067c,%edi            这里0x40067c指向字符串"%s
    "
      400574:       b8 00 00 00 00          mov    $0x0,%eax
      400579:       e8 ea fe ff ff          callq  400468 <printf@plt>
      40057e:       b8 00 00 00 00          mov    $0x0,%eax
    

    差不多到这里问题就追踪出来了。由于是在64位系统上执行,因此eax只取了32位,赋给esi也只取了32位。而其实在64位系统上,strerror返回的是char *指针,应该是64位的。借用一张他人绘制的rax,eax间的关系图:

    |63..32|31..16|15-8|7-0|
                   |AH.|AL.|
                   |AX.....|
           |EAX............|
    |RAX...................|

    结论:

    strerror函数声明在string.h头文件里,由于没有包含该头文件,编译器将strerror的返回值当做了int类型来处理,而int类型是32位的,因此当做指针传给printf,就跪了。后来我编译的时候打开warning,其实已经给出了问题所在:

    cc -Wall test.c 
    
    test.c: In function `main':
    test.c:6: warning: implicit declaration of function `strerror'
    test.c:6: warning: format argument is not a pointer (arg 2)
    

    所以再一次的,请编译时开启warning提示。

  • 相关阅读:
    字号、pt、px、em换算对照表
    回车自动提交 禁止回车自动提交
    working copy locked (svn)
    xUnit asp.net单元测试工具基本使用
    防御网站攻击 1
    Access restriction: The type HttpServlet is not accessible due to restriction on required library xxxx\servletapi.jar
    【转载】将sqlserver表中的数据导出sql语句或生成insert into语句
    动态切换数据源(spring+hibernate)
    MSSQL2005移植到MYSQL 5.0
    C++ Primer 4 CPP Note 2.1.1 整型和浮点型
  • 原文地址:https://www.cnblogs.com/driftcloudy/p/4971616.html
Copyright © 2020-2023  润新知