徐土豆
认证:优质创作者
所在专题目录 查看专题
C语言中去除不必要的内存引用可以有效地提高性能
C语言中内循环和外循环的位置可能产生性能上的区别
[C语言朝花夕拾] C语言中的命令行输入参数判断
用“位操作”取代“取模操作”判断奇数偶数
c语言运行时出现segment fault的原因
一文理解C语言中的volatile修饰符
作者动态 更多
给定计算预算下的最佳LLM模型尺寸与预训练数据量分配
05-19 09:33
大模型推理时的尺度扩展定律
05-18 10:32
世界多胞体与世界模型
05-13 09:42
奖励模型中的尺度扩展定律和奖励劫持
05-12 08:41
MeCo——给预训练数据增加源信息,就能减少33%的训练量并且提升效果
05-08 09:13

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
关注 52
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧