徐土豆
认证:优质创作者
所在专题目录 查看专题
C语言中去除不必要的内存引用可以有效地提高性能
C语言中内循环和外循环的位置可能产生性能上的区别
[C语言朝花夕拾] C语言中的命令行输入参数判断
用“位操作”取代“取模操作”判断奇数偶数
c语言运行时出现segment fault的原因
一文理解C语言中的volatile修饰符
作者动态 更多
【论文极速看】ERNIE 3.0 通过用知识图谱加强的语言模型
2星期前
工作一年时期的土豆总结——复杂度和困难度
10-22 14:24
【见闻录系列】我所理解的“业务”
10-19 11:25
markdown数学公式编辑
10-17 13:58
在linux系统上部署FTP服务时进行权限管理(利用chown,chmod命令实现)
10-09 10:24

c语言运行时出现segment fault的原因

本文转自徐飞翔的“c语言运行时出现segment fault的原因
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

segment fault段错误是在编程报错中经常出现的,特别是在c语言编程中,尤其常见,其原因本质上上是访问了非法(不属于这个程序)的内存地址空间,具体来说有以下几种情况:

  1. 局部变量定义中,使用了过大的局部变量,大于了系统给之的栈(stack)的大小,因此报错。比如以下代码在linux环境下,就可能出现段错误报错:
    void foo(){
    	float vars[10000][10000];
    }​

    代码很简单,就是在栈上划出了一个很大的连续内存空间,翻译成汇编如:

    mov $100000016, %rsp
    # 还有多出的16个字节是上下文切换需要的内存,frame pointer %rbp, return address等,
    # 同时如果用gcc等编译的,还要考虑其内存对齐的要求,即是其是16字节的倍数。​

    这个栈大小可能超出了系统给定每个程序的栈的大小,可以通过shell命令ulimit -s进行查看系统给定的栈大小,比如笔者的就是:

    user@ubuntu: ulimit -s 
    8192​

    注意这里都是以1024字节(1KB)为单位的,因此默认的就是8MB的栈大小,如果你的程序需要更大的栈空间,那么可以通过

    ulimit -s 1000000​

    类似这样的命令去重定义最大的栈大小。

  2. stack overflow栈溢出 C语言是没有对数组的边界检测的,这样在实际应用中常常会导致越界的问题,我们知道,程序的栈如下图所示:

    考察以下代码:

    void foo(){
    	int vars[100];
    	vars[100] = 0;
    	vars[101] = 0;
    	vars[102] = 0;
    	vars[103] = 0;
    }​

    当然,我们知道,我们对该数组vars只能检索到vars[99],因为其索引范围是[0,99],但是这种超出了理论上的索引边界(越界)的“低级错误”确是在实际代码中经常出现的bug的根源之一。从上图的程序栈我们可以看出,如果栈中的变量边界溢出,那么可能会对一些上下文信息,比如return address进行期望之外的修改,导致难以预料的错误(比如无法返回到调用函数,或者返回到不该返回的地址,这里容易被黑客进行栈溢出攻击),因此操作系统一般会检测这种段错误,同时报错segment fault

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 3
收藏 3
关注 50
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧