起航学习网

- 让每个人都能学到最前沿新知识、新技能!
起航学习网
当前位置: 起航学习网 > 短期培训 > 编程语言 > 想写个崩溃的C语言小程序 真是好主意

想写个崩溃的C语言小程序 真是好主意

时间:2018-11-22 11:26:42来源:编程网 作者:IT培训网 已有: 名学员访问该课程

  快捷搜索:C语言小程序

前言:当C程序在编译的时候,编译器会产生一个或更多对象文件,文件里有对于用到的库和全程对象(函数和变量)的符号索引。然后这些对象文件会被进行链接,这时符号索引被地址所代替,就产生了一个可执行文件。

最短的崩溃程序(C语言版)

想写个崩溃的C语言小程序,看起来是个奇怪的主意,不过在我曾经教过的一门实验课上,这是作业之一!实际上,这是一件非常有教学意义的事情。

通常学生们要么尝试反向引用一个非法地址,要么就是除0.除0会引发SIGFPE信号(浮点异常)。这里有一个小例子程序,使用除零方法来使之崩溃:

int main

{

return 1/0;

}

我们也可以删掉return关键字,但是当我这么做的时候gcc不会为这些语句生成可执行代码,即便优化选项被disable掉了。我们还可以通过把上面的语句改成赋值语句,使上面的代码改变一些特征:

i;

int main

{

i=1/0;

}

注意我声明了一个没有类型的i。这样的代码在C89标准里是有效的,因为所有的声明都有隐形的缺省类型int。在C99和其他一些C标准里这是一个错误。假定我们写的是C89代码,那么我们甚至可以使用隐形int来声明main函数:

i;

main

{

i=1/0;

}

那是相当短的代码了 — 如果我们不把用于缩进的空格计算进来,只有16个字符。然而,我们还可以做得更好!

当C程序在编译的时候,编译器会产生一个或更多对象文件,文件里有对于用到的库和全程对象(函数和变量)的符号索引。然后这些对象文件会被进行链接,这时符号索引被地址所代替,就产生了一个可执行文件。

编译器在一个对象文件里提供了一个调用main函数的入口点。调用main函数意味着我们试图执行在存储在main函数链接的位置所对应地址里的指令。

有趣的是,链接器对于不同对象的类型是没有概念的,它只知道它们的地址。所以,如果我们用一个常规的全程变量替换main函数,编译器会高兴地build对象文件,因为它不关心对象main的类型是什么;链接器也会高兴地链接它,因为它只关心main函数对应的地址。

所以,考虑这个C程序:

int main=0;

这个程序会编译成一个可执行文件,它会试图调用地址0,而0并不是我们能够访问的地址,这样我们会得到SIGSEGV信号(分段错误)。

更正:我前面关于这个程序崩溃的原因分析是错的。这个程序会试图按函数方式去执行main,而这样不会奏效,因为编译器把它放到了不可执行的数据段。所以变量main初始化为什么值都无所谓了。(感谢Zack的纠正)

现在我们已经非常接近最小的崩溃的C程序了。我们可以利用这个技巧,配合隐形int类型,来把它进一步缩短。

main=0;

还有,C里的全局变量都会隐形地初始化为0,所以上面的代码就等同于:

main;

好了,现在我们得到了最短的崩溃的C程序!

补充:

Hacker News用户femto指出,编译和链接一个空文件也是可能的。我没有发布这个是因为gcc会拒绝编译和链接这样的程序,它会要求分开编译和链接的过程。

另外,要是我们再学究一点,我应该指出我这里的“全局”变量意思是说“静态”变量。

文章出自:http://qh.itpxw.cn/peixun/software/201844687.html

文章标题:想写个崩溃的C语言小程序 真是好主意



免责声明:本站文章均由入驻起航学习网的会员所发或者网络转载,所述观点仅代表作者本人,不代表起航学习网立场。如有侵权或者其他问题,请联系举报,必删。侵权投诉

(责任编辑:IT培训网)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
培训学校
IT培训网 访问该机构站点 报名留言 加为好友 用户等级:注册会员 用户级别:10 机构名称:IT培训网 联 系 人:罗老师 联系电话:13783581536 联系手机:13783581536 在线客服:起航学习网客服 在 线 QQ:起航学习网客服 电子邮件: 网站域名:http://www.itpxw.cn 注册时间:2016-07-18 11:07 最后登录:2024-02-20 13:02
推荐内容