zoukankan      html  css  js  c++  java
  • 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提示。

  • 相关阅读:
    些许注意事项(初学)
    第一个方法(初学)
    重载(初学)
    数组(初学)
    文件下载(初学)
    javaweb中上传视频,并且播放,用上传视频信息为例
    javaweb中上传图片并显示图片,用我要上传课程信息(里面包括照片)这个例子说明
    从后台servlet中,获取jsp页面输入的值,来删除用户一行信息
    第二式 观察者模式
    第一式 策略模式
  • 原文地址:https://www.cnblogs.com/driftcloudy/p/4971616.html
Copyright © 2011-2022 走看看