免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 62166 | 回复: 6
打印 上一主题 下一主题

月经结贴 -- 《Segmentation Fault in Linux》 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-21 17:23 |显示全部楼层 |倒序浏览
写在前面的话
    最近CU(chinaunix)出现了很多问segmentation fault的帖子,其实这也是个“月经贴”了,泡CU几年,每个月都有人问。为了减少重复回帖,笔者结合自己的经验,总结了SIGSEGV在Linux中产生的机理,并用实际例子概括哪些编程错误容易引发SIGSEGV。由于本人经验有限,文中难免有疏漏和错误,请发现的朋友发信到xing5820@163.com指正,笔者好即使修改。

内容提要
  本文简单介绍了Segmentation fault发生的原因,结合实际例子描述了内核向用户态程序发送SIGSEGV信号的流程。文中以实例回答了常见的一些SIGSEGV问题,例如“为什么函数返回了栈还可以访问?”、“为什么free()后的内存仍然可以使用”、“为什么我遇到的是SIGSEGV而不是SIGILL信号”等。最后笔者结合自己的经验,列举了一些预防SIGSEGV的编程习惯,供大家参考。SIGSEGV严格依赖操作系统、编译器、硬件平台,本文基于Linux、GCC、32bit IA32架构,但对其他平台操作系统也有借鉴意义。


大家在阅读的过程中发现什么错误,或我没有讲到的segfault情况,请及时指出,我好更正。

Segmentation fault in Linux.pdf

309.26 KB, 下载次数: 4416

论坛徽章:
0
2 [报告]
发表于 2009-12-21 18:04 |显示全部楼层
原帖由 OwnWaterloo 于 2009-12-21 17:39 发表
看了一下……  看来那帖子我是白费口水了……
表面上说接受, 实际上依然是在鼓励大家编写不可移植代码 —— 而且, 并不是为了得到什么实际的好处。

哈哈哈,我是接受你看问题的角度,其它的我持保留意见。
至于这篇文章嘛,已经不在标准范畴了,我一开始也说,这是非常平台相关的

论坛徽章:
0
3 [报告]
发表于 2009-12-21 18:35 |显示全部楼层
原帖由 albcamus 于 2009-12-21 18:13 发表
楼主应该写书啊, 做独立技术写作也不错…

哈哈哈,哪儿有那功夫,平时忙的要死,泡个论坛都是忙里偷闲了。
上次不是chen xu过来提到说我泡CU,我差不多都要忘了有好久没上过了。
写书真是吃力不讨好的事情,就那本在内核版打广告的书,我虽然只写了一章加一节,但被老板当较字工人让去review全书,那真是一个字一个字得看,一个字一个字的改啊,惨的不行。发现错误还要去请教那些大牛原意是什么的,然后帮他们重写。还是写点这种小文好了,全凭兴趣,想怎么写就怎么写
中国人搞技术啊,真是为了讨生活,除非像老外衣食无忧纯粹的"working for fun"差不多。

论坛徽章:
0
4 [报告]
发表于 2009-12-21 18:53 |显示全部楼层
原帖由 OwnWaterloo 于 2009-12-21 18:18 发表
char a[] = "hello";
char* p;

for ( p = a+sizeof(a)-2; p>=a; p-- )
      printf("%c\n", *p );

与:

for ( p = a+sizeof(a)-2; p!=a; p-- )
      printf("%c\n", *p );


效果是一样的: 如 ...

嘿嘿,我理解你的意思,觉得标准都规定了好了,为什么就不好好按标准写呢。
这里面一是有历史原因,一是不方便。
比如你这里这个例子
for ( p = a+sizeof(a)-1; p!=a /* or p>=a */; ) {
      --p;
      printf("%c\n", *p );
}
先--p就把空字符去掉了,很可能别人原意就要打印这个空字符。p!=a,又少打一个h,所以我在写这个例子时都是跳出循环后再打一次。
标准规定的是完美情况,但现实中要想写出完美的代码时很难的,所以我说有一些既成事实的标准。比如说按标准写:
int a = 70000;
严格来说这样写是不对的,因为不知道这个int的长度,如果是2字节,它就溢出了。怎么办呢,写成
int32_t a = 70000;
是保险的。这意味着我们就不随便使用int、short、long之类的变量的,一定要#include <stdint.h>。但那么多的教材、那么多的书籍都在这样用,
从一学C语言就开始这样用,突然就告诉说这样不对,不严格,在某些情况下会出错。但实际上99%的时间我们写不是跨平台程序,要把所有细节都严格按照标准,
基本上就寸步难行了。所以对于这种情况,人们大都follow的那些即成事实的标准。也正是因为有这些既成事实的标准了,所以几乎也不会出现你说那种特殊的编译器,出现了也不会被市场接受。

历史原因也有很多,比如大家都知道宏不好,定义常量会污染名字空间,应该用enum。写函数没有类型检查,应该用inline函数。但它就用了这么久了,那么多知名项目都在用,都这样用,所以也有很多人follow。

OwnWaterloo你可能是个追求完美的人,但现实中大部分时候都不是完美的。我倒不是鼓励大家不遵守标准,我只是从我的观点陈述一种事实,即它可能不符合标准,但它99%的时间不会出错,至于如何抉择,就看个人了。

>>算了, 别人写的代码是否可移植关我鸟事 ……   大家爱怎么写就怎么写好了……
至于这个嘛,你也别急,现实中和别人意见相左的情况很多,其实我们只要了解了别人的观点,理解他的出发点,然后在心中坚持自己的理念即可。至于别人怎么做怎么想,那真是管我们鸟事

论坛徽章:
0
5 [报告]
发表于 2009-12-21 19:25 |显示全部楼层
原帖由 OwnWaterloo 于 2009-12-21 19:15 发表
我是故意把空字符去掉的……   上面2份代码是-2 ……
要输出空字符的话:
for ( p = a+sizeof(a)/*-1 把这个-1去掉*/; p!=a /* or p>=a */; ) {
      --p;
      printf("%c\n", *p );
}

那么, 在逆 ...

是我看错了,你把 --p提出来了。

这样是很好,但一般人不会相到这样写。就像你后来说了,人们不会接受指针算术溢出会导致错误。

[ 本帖最后由 zx_wing 于 2009-12-21 19:29 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2009-12-21 19:30 |显示全部楼层
原帖由 OwnWaterloo 于 2009-12-21 19:29 发表
当真?

你回的真快,我刚改你就回了。见上

论坛徽章:
0
7 [报告]
发表于 2009-12-22 21:38 |显示全部楼层
原帖由 mik 于 2009-12-22 20:24 发表
zx_wing 花了不少心思啊

zx_wing 把你写过的专集再添加、整理、修饰、校对一下,可以出书了。

至少比市面上某些作者好多了。

老大过奖了
写过的东西还不多。反正凭兴趣,写点小东西,集多了也是件有成就感的事情
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP