• 函数栈溢出引起的段错误segmentation fault


    遇到了一个奇怪的问题:

    有一个回调函数中发生了段错误,但经检查也没有什么明显的错误,然后用排除法一点一点屏蔽,最后定位在一个函数里出错,但这个函数没什么明显错误。最后把入口参数改为引用传递就不报错误。 

    但隔了一段时间这个函数又报错了,原因是我加一行代码,但这行代码就是一个赋值语句;于是我不甘心,又开始排除法,最后定位到一个变量,加上它报错,不加就不报错;我一直怀疑是不是linux对一个函数的大小有限制;于是将这个函数换成全局变量,而在此函数中用的此变量时候采用指针,诶,不再报段错误了,世界终于安静了。

    但不知是根本原因是什么,于是就疯狂的在网上找呀找,也找到了一点线索,原来的这个限制函数内局部变量大小的东西叫函数栈,而linux中这函数栈大小中系统定义的,程序中函数分配的栈一旦超出了这个大小,就会segmentation fault.

    下面将搜集到的资料整理一下。

    查看函数栈的大小:

    linux函数栈空间大小的shell命令是:ulimit -s

    stack size              (kbytes, -s) 8192

    如果上8192,单位是KB,总共8M

    修改函数栈的大小:

    linux函数栈空间大小的shell命令是:ulimit -s 数字

    函数栈发生错误的经典场景:

    1、函数如果是递归函数,且函数内部包含较大的变量,那么非常容易栈溢出。

    2、函数使用了某数组,数组大小由一个宏定义或常量指定,当后期代码升级的时候,加大了宏定义或常量的大小,导致原先的代码出现栈溢出。代码扩展性差。

    函数栈大小限制导致段错误实例: 

     #include <string.h>   

     #include <stdio.h>   

     int main()   

     {   

         int a [10 * 1024 * 1024];   

         a[0] = 1;   

         return 0;   

     }  

    上面的代码运行就会报段错误
    原因:
    ulimit -s
    10240
    可以看到linux配置的线程栈的大小为10M
    函数里面使用了两个大的数组,超出了linux线程栈大小配置的上限,而函数调用是需要栈的,当空间不足,导致越界,所以core掉。所以在函数中劲量少使用大的数据,而是使用堆分配内存(全局变量或Malloc)。

    注意:
    为什么加上a[0] = 1;才会core,不加是不会core
    因为在linux中,只有在使用时候才会分配内存,如果没有a[0]=1;并不会在栈上为a数组分配内存,所以不会导致core掉。

  • 相关阅读:
    HDU
    稀疏表(ST / Sparse Table)
    HDU
    HDU
    树状数组
    用 BitArray 来编写埃拉托斯特尼筛法
    BitArray 内置是逆序存储, 因此要自行实现正序输出
    位运算,位移,窗体
    按位运算,窗体程序,And,Or,Xor
    基数排序
  • 原文地址:https://www.cnblogs.com/tham/p/6827288.html
Copyright © 2020-2023  润新知