linux下C编程free()时出现飘忽诡异的段错误(核心已转储)问题
来源:互联网 发布:谷歌程序员平均工资 编辑:程序博客网 时间:2024/05/22 06:33
先说一下问题现场。
代码如下
运行时出现段错误,“what”随机出现,也就是说可能是打印前出现段错误,也可能是打印后出现段错误。但最终定位就在这几行free里面。
人格保证,各个指针都有初始化,都有检查,代码这里没有列出来而已。
困扰了我2,3天时间,因为完全无法解释free出现段错误这个问题背后的原因,指针是绝对正常的。后来查阅了大量资料,终于理了个脉络出来,大概知道怎么回事了。进一步的debug还在进行中。。。
提醒:这只是泛泛而谈,因为内存管理的问题跟语言、编译器、操作系统都有关系,windows下和Linux就大不相同,本文也没有想精确定位,只是给个思路而已。
下面是具体分析,首先是参考资料
参考资料
编号
名称
作者
内容
1
http://baike.baidu.com/link?url=-1euetbsnxgUONmVs3jA5eexMlkm5GJVTRIrcn1z3KwFVrDT-Ei6qtcxKxWAm229u6pWvOq0KKnWuWogahdeoK
“堆栈”的百度百科,杂七杂八讲了一大堆东西。
2
http://imatlab.lofter.com/post/286ffc_a6ead7
局部变量数组过大造成的段错误
3
http://www.oschina.net/question/617142_65867?sort=default&p=1#answers
典型的数组越界
4
http://blog.csdn.net/misskissc/article/details/10757975
子函数返回的时候,数据区、栈区的内容是否有效的问题。
5
http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html
各种段错误及其调试方法
6
http://bbs.chinaunix.net/thread-1332271-1-1.html
局部变量作为实参传递出现错误
7
http://blog.csdn.net/wind19/article/details/5964090
C中的内存管理,
8
http://blog.csdn.net/wind19/article/details/5964137
C中堆和栈的数组越界,局部变量是放在栈中的
9
http://www.cs.ucsb.edu/~pconrad/cs16/10W/extraLabs/el01/
UCSB的C语言课程关于段错误的实验内容
出现段错误的情况,基本还是栈溢出(使用的内存空间大于系统默认分配的栈空间)[2][5]
数组越界[3]
访问不存在的地址(指针NULL)[5]
访问系统保护的内存地址[5]
访问只读的内存地址[5]
关于入栈、出栈 [1]讲了一点,在子函数调用的时候的情况,注意这只是多数情况,具体的系统很可能不一样
栈: 在函数调用时,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向函数的返回地址,也就是主函数中的下一条指令的地址,程序由该点继续运行。
[5]里面讲了很复杂的调试方法,但用在IDE里面用gdb可以很方便找到位置。关键是linux下,对于段错误的报警存在可能的偏差!
比如[3],在数组越界的时候并未实时报警,而是在free的时候才报警。
实际上我也是这种情况,应该是volthisframe->Tops和Bots都越界了,但是到free的时候才随机选一个报警。甚至是下一个free才报警。定位都很困难,定位到free也不解决任何问题。。。
OK,总结如下,主要是[7][8]说的最清楚
BSS、数据段、代码段是编译器预分配的,
BSS段即未初始化的全局变量和静态变量的空间,读写。运行时初始化
数据段即已初始化的全局变量和静态变量的空间,读写。已由编译器初始化
代码段,就是代码空间,有的编译器和系统允许修改这一部分。
堆栈都由系统分配。
堆:很多系统都是从虚拟内存里面直接给,大小几乎不限。malloc和free类的内存空间就在这里。
栈,这个是重点
系统指定的空间,每个程序大小是统一的。linux下默认是8M。用ulimit查看修改。
局部变量就放在这里面,如果出现子函数调用的情况,除了子函数的局部变量和子函数的实参(其实也是局部变量)之外,父函数的返回地址也会入栈[1]。返回时如有返回值,也会压入栈中。调用时的入栈顺序是:
返回地址、实参、局部变量。
出栈相反。
栈就会带来很多问题。看了[4],我再总结如下:
局部变量的有效区间:本函数的存在时空。本函数返回之后,栈的内容其实还在,但随时可能被其它函数入栈顶替。
局部变量的地址作为实参传入:入栈的是父函数的局部变量的地址,其实是可以的,因为这时候父函数肯定还没结束。栈内空间依然保留,而且可读写。
根据[7],局部变量数组越界其实是在栈里面,而全局变量数组越界是在数据段或者BSS段里面。
而堆里面越界是在系统的虚拟内存里面。
Bingle!
最终原因:
很可能这是造成堆里面越界不能及时反映的原因,等到free的时候系统才发现不对头。因为使用的时候系统也没有随时监视,系统无法得知。
但无法理解系统为啥free这时候会发现不对,free里面可能有检查。猜测有记录使用了那些堆。
所以,我应该是指针在过程中使用的时候出现越界的情况,但在free时系统才报错,而且还不一定在哪儿报,可能是越界的指针本身free时,也可能是被侵犯的指针free时。我这里就是volthisframe->Tops和volthisframe->Bots两个指针都越界了(这两个是同步用的),但有时会在free(volthisframe->SCTops)时报错!
- linux下C编程free()时出现飘忽诡异的段错误(核心已转储)问题
- linux下C编程free()时出现飘忽诡异的段错误(核心已转储)问题
- Linux下运行C++程序出现“段错误(核心已转储)”的原因
- Qt编程中诡异的段错误
- Qt编程中诡异的段错误
- Linux下的c编程 出现问题
- 段错误(核心已转储)问题的分析方法
- 解决Linux c语言运行时候“段错误 (核心已转储)”问题-采用gdb 解决
- C语言基础问题2 段错误(核心已储存)修改错误的经历
- linux下C语言编程 一个堆栈错误的原因:*** glibc detected *** ./test: free(): invalid pointer:
- linux 下 C 编程 C版的try catch 捕捉段错误和异常处理
- Linux下程序出现段错误的调试解决方法
- linux在main函数结尾出现段错误的问题
- C语言再学习 -- 段错误(核心已转储)
- C语言再学习 -- 段错误(核心已转储)
- ubuntu C 语言 段错误 (核心已转储)
- ubuntu C 语言 段错误 (核心已转储)
- linux下编程的段错误的解决办法
- 安卓开发-自定义view(二)-自定义属性
- [bzoj1684][Usaco2005 Oct]Close Encounter
- 带钓鱼岛的中国地图geoJson
- sql server 计算两个经纬度点之间的距离
- Echarts条形图实战
- linux下C编程free()时出现飘忽诡异的段错误(核心已转储)问题
- 编程题:栈的压入弹出序列
- powerdesigner ER图建模教程
- ios项目中调用百度、高德、本机地图导航(二)
- 图片懒加载怎么写?
- CodeForces
- JavaScript数据类型
- 数值处理
- 利用原生的 file input上传 图片