strerror的坑
最近写的一段代码,总是出core,精简了一下,稳定复现。
#include <stdio.h>
#include <errno.h> int main()
{
printf("%s\n", 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\n"
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提示。
strerror的坑的更多相关文章
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- Spark踩坑记——Spark Streaming+Kafka
[TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- 踩石行动:ViewPager无限轮播的坑
2016-6-19 前言 View轮播效果在app中很常见,一想到左右滑动的效果就很容易想到使用ViewPager来实现.对于像我们常说的banner这样的效果,具备无限滑动的功能是可以用ViewPa ...
- 为C# as 类型转换及Assembly.LoadFrom埋坑!
背景: 不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有) 效果是这样的: 之后,有小部分用户反映,工具用不了(没反应或有异常)~~~ 然后,建议小部分用户换个电脑 ...
- 首个threejs项目-前端填坑指南
第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...
- dll文件32位64位检测工具以及Windows文件夹SysWow64的坑
自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...
- 关于微软HttpClient使用,避免踩坑
最近公司对于WebApi的场景使用也越来越加大了,随之而来就是Api的客户端工具我们使用哪个?我们最常用的估计就是HttpClient,在微软类库中命名空间地址:System.Net.Http,是一个 ...
随机推荐
- C语言读写配置文件--转载
http://www.oschina.net/code/snippet_4873_2503 [].[代码] CException.h 跳至 [] [] [] /******************** ...
- 《TCP/IP详解》
TCP/IP概述 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本 ...
- [CPP] new delete
前言 今天我们来谈一谈CPP中很关键的两个操作 new 和 delete ,关于他们与析构函数的关系.动态分配的内存空间.new array ( new[] ) 和 delete array ( de ...
- 非科班双非本科投的337家Java后台(励志)
考试结束,班级平均分只拿到了年级第二,班主任于是问道:大家都知道世界第一高峰珠穆朗玛峰,有人知道世界第二高峰是什么吗?正当班主任要继续发话,只听到角落默默想起来一个声音:”乔戈里峰” 前言 文章出自h ...
- 如何构建ASP.NET MVC4&JQuery&AJax&JSon示例
背景: 博客中将构建一个小示例,用于演示在ASP.NET MVC4项目中,如何使用JQuery Ajax. 步骤: 1,添加控制器(HomeController)和动作方法(Index),并为Inde ...
- 01.CLR的执行模型
在非托管的C/C++中,可以进行一些底层的操作 "公共语言运行时"(CLR)是一个可由多种编程语言使用的"运行时" CLR的核心功能包 ...
- Docker学习之Docker镜像基本使用
Docker学习之Docker镜像基本使用 获取镜像 命令格式:docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] 例如: docker pull ...
- django中的template部分
模版部分 取值 {{key}} 语句块 {%for item in data%} {%extends 'base.html'%} 深度变量的查找(万能的句点号) 在到目前为止的例子中,我们通过 con ...
- springboot基本注解
声明Bean的注解: @Component组件 @Service service层 @Respository dao层 @Controller 注入Bean的注解: @Autowired Spring ...
- golang 编码转化
在网上搜索golang编码转化时,我们经常看到的文章是使用下面一些第三方库: https://github.com/djimenez/iconv-go https://github.com/qiniu ...