码迷,mamicode.com
首页 > 系统相关 > 详细

linux下C编程free()时出现飘忽诡异的段错误(核心已转储)问题

时间:2015-05-07 16:41:29      阅读:305      评论:0      收藏:0      [点我收藏+]

标签:linux   内存管理   内存分配   c语言   指针   

先说一下问题现场。

代码如下

free(volthisframe->Tops);
free(volthisframe->Bots);
printf("what\n");
free(volthisframe->SCTops);
free(volthisframe->SCBots);




运行时出现段错误,“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/

 

UCSBC语言课程关于段错误的实验内容



这个问题跟C语言和编译器的内存分配,linux的内存管理都有关系,一个一个来。


出现段错误的情况,基本还是栈溢出(使用的内存空间大于系统默认分配的栈空间)[2][5]

数组越界[3]

访问不存在的地址(指针NULL[5]

访问系统保护的内存地址[5]

访问只读的内存地址[5]

 

 

关于入栈、出栈 [1]讲了一点,在子函数调用的时候的情况,注意这只是多数情况,具体的系统很可能不一样

栈: 在函数调用时,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向函数的返回地址,也就是主函数中的下一条指令的地址,程序由该点继续运行。

 

 

[5]里面讲了很复杂的调试方法,但用在IDE里面用gdb可以很方便找到位置。关键是linux下,对于段错误的报警存在可能的偏差!

比如[3],在数组越界的时候并未实时报警,而是在free的时候才报警。

实际上我也是这种情况,应该是volthisframe->TopsBots都越界了,但是到free的时候才随机选一个报警。甚至是下一个free才报警。定位都很困难,定位到free也不解决任何问题。。。

 

OK,总结如下,主要是[7][8]说的最清楚

 

技术分享

 

BSS、数据段、代码段是编译器预分配的,

BSS段即未初始化的全局变量和静态变量的空间,读写。运行时初始化

数据段即已初始化的全局变量和静态变量的空间,读写。已由编译器初始化

代码段,就是代码空间,有的编译器和系统允许修改这一部分。

 

 

堆栈都由系统分配。

堆:很多系统都是从虚拟内存里面直接给,大小几乎不限。mallocfree类的内存空间就在这里。

 

栈,这个是重点

系统指定的空间,每个程序大小是统一的。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语言   指针   

原文地址:http://blog.csdn.net/cd_keanu/article/details/45562449

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!