zoukankan      html  css  js  c++  java
  • 函数栈溢出引起的段错误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掉。

  • 相关阅读:
    从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
    从零搭建Spring Boot脚手架(3):集成mybatis
    从零搭建Spring Boot脚手架(2):增加通用的功能
    从零搭建Spring Boot脚手架(1):开篇以及技术选型
    Hibernate Validator校验参数全攻略
    Spring Data R2DBC响应式操作MySQL
    Spring Security 实战干货:从零手写一个验证码登录
    Spring Security 实战干货:图解用户是如何登录的
    基于.NetCore3.1系列 —— 日志记录之日志核心要素揭秘
    基于.NetCore3.1系列 —— 日志记录之日志配置揭秘
  • 原文地址:https://www.cnblogs.com/tham/p/6827288.html
Copyright © 2011-2022 走看看