[转载]一个指针参数引发的血案
2010-07-11 16:24
489 查看
原文链接:http://blog.odichy.org/tag/malloc
今天在阅览室看《算法导论》,顺便用C写了链表相关的算法,结果在初始化链表的时候出现了问题,出现了Segmentation fault。先来看看错误的代码,省略一些定义了:
这个是想在一个方法里面初始化链表,因为malloc是在堆上分配内存,所以其分配的空间不会随函数的结束而从栈上消失,所以自然而然的想把这的值 直接给li,以便在接下来的程序中引用。但是编译执行时显示Segmentation fault,不用想肯定是main中的li仍然指向NULL。开始比较疑惑,因为一般来说传一个指针进去,是会改变其指向的内容的,就好象是面向对象中的 按引用调用一样,这里为什么会出错呢?如果把init函数的代码段移回main中,程序运行没什么问题的,那么肯定问题出在malloc分配的空间上。
分析一下这个程序执行的过程,首先声明一个list *类型的参数,也就是一个可以指向list类型的指针,因为还没赋值,所以其空间内存的数据可能是任何东西。然后就是调用init方法,注意此时所传递的 是main.li这个变量内存的值,因此对于init.li,其值是main.li的值,它只是main.li的一个拷贝,但是它的存储空间是分配在 init函数活动栈上的,因此此时将malloc分配的堆内存地址赋给init.li时只是改变了init活动栈上的li的值,并未真正去改变 main.li这个main的活动栈上的li的值。因此当init函数完成调用,返回后,其活动栈将销毁,也就是将我们刚刚malloc的那块堆内存地址 给销毁了,此时就造成了内存泄漏。而我们再通过main.li调用时,其实它还是没有分配过存储空间的,所以产生了Segmentation fault。
分析明白产生错误的原因后,自然就好改了,要么将malloc分配的指针返回,要么将参数改成一个指针的指针(即main.li的地址),按第二个方法更改程序如下:
由此可见,其实在指针做参数时,还是存在一定的陷阱的,如果不清楚程度堆栈的建立过程,很容易出现内存泄漏,而且在看不懂GAS汇编的情况下,要想通过二进制机器码分析出问题所在,还是有一定困难的。在C中的函数存在很多陷阱,用的时候一定要时刻小心才是。
今天在阅览室看《算法导论》,顺便用C写了链表相关的算法,结果在初始化链表的时候出现了问题,出现了Segmentation fault。先来看看错误的代码,省略一些定义了:
1 2 3 4 5 6 7 8 9 10 11 12 13 | int main(void) { list *li; init(li); insert(li, 5); //main函数以下省略,insert为插入一个元素到链表 } static void init(list *li) { li = (list *)malloc(sizeof(list)); //init函数以下省略 } |
分析一下这个程序执行的过程,首先声明一个list *类型的参数,也就是一个可以指向list类型的指针,因为还没赋值,所以其空间内存的数据可能是任何东西。然后就是调用init方法,注意此时所传递的 是main.li这个变量内存的值,因此对于init.li,其值是main.li的值,它只是main.li的一个拷贝,但是它的存储空间是分配在 init函数活动栈上的,因此此时将malloc分配的堆内存地址赋给init.li时只是改变了init活动栈上的li的值,并未真正去改变 main.li这个main的活动栈上的li的值。因此当init函数完成调用,返回后,其活动栈将销毁,也就是将我们刚刚malloc的那块堆内存地址 给销毁了,此时就造成了内存泄漏。而我们再通过main.li调用时,其实它还是没有分配过存储空间的,所以产生了Segmentation fault。
分析明白产生错误的原因后,自然就好改了,要么将malloc分配的指针返回,要么将参数改成一个指针的指针(即main.li的地址),按第二个方法更改程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | int main(void) { list *li; init(&li); insert(li, 5); //main函数以下省略,insert为插入一个元素到链表 } static void init(list **li) { *li = (list *)malloc(sizeof(list)); //init函数以下省略 } |
相关文章推荐
- 一个Sqrt函数引发的血案(转载)
- 【转载】一个Sqrt函数引发的血案
- Objc中2维指针作为输出参数时由ARC及@autoreleasepool引发的血案
- 【转载】jQuery.unique引发一个血案
- 2018_03_13 一个 java.lang.IllegalArgumentException 非法参数异常引发的血案
- 【坑】一个线程参数引发的血案
- 一个Tomcat配置参数引发的血案
- [转载]经典搞笑:一个BUG引发的血案|为程序员打造的年终大片
- 一个指针的引用引发的血案
- 一个MSS参数引发的“血案”
- 一个“Sprng轮子”引发的“血案”(3)
- 一个“Spring轮子”引发的“血案”(6)
- 一个“Spring轮子”引发的“血案”(4)
- 一个“Spring轮子”引发的“血案”(2)
- 一个“Spring轮子”引发的“血案”(6)
- 一个“Spring轮子”引发的“血案”(6)
- 一个“Sprng轮子”引发的“血案”(3)
- 一个shell脚本引发的对于分号(;)和$#的使用说明(转载)
- 一个无锁消息队列引发的血案(一)——地:起因
- 一个无锁消息队列引发的血案(二)——月:混合自旋锁