2012年(5)
分类:
2012-11-16 11:07:56
原文地址:C语言深度解刨——学习笔记(内存管理) 作者:11wping
内存管理
对于程序员,一般来说,我们可以简单的理解为内存分为三个部分:静态区,栈,堆。
静态区:保存自动全局变量和static 变量(包括static 全局和局部变量)。静态区的内容
在总个程序的生命周期内都存在,由编译器在编译的时候分配。
栈:保存局部变量。栈上的内容只在函数的范围内存在,当函数运行结束,这些内容
也会自动被销毁。其特点是效率高,但空间大小有限。
堆:由malloc 系列函数或new 操作符分配的内存。其生命周期由free 或delete 决定。
在没有释放之前一直存在,直到程序结束。其特点是使用灵活,空间比较大,但容易出错。
常见的内存错误及对策——指针没有指向一块合法的内存
结构体成员指针未初始化
没有为结构体指针分配足够的内存
函数的入口校验:不管什么时候,我们使用指针之前一定要确保指针是有效的。
一般在函数入口处使用assert(NULL != p)对参数进行校验。在非参数的地方使用
if(NULL != p)来校验。但这都有一个要求,即p 在定义的同时被初始化为NULL 了。
assert 是一个宏,而不是函数,包含在assert.h 头文件中。如果其后面括号里的值为假,
则程序终止运行,并提示出错;如果后面括号里的值为真,则继续运行后面的代码。这个
宏只在Debug 版本上起作用,而在Release 版本被编译器完全优化掉,这样就不会影响代码
的性能。
为指针分配的内存太小
内存分配成功,但并未初始化:犯这个错误往往是由于没有初始化的概念或者是以为内存分配好之后其值自然为0。
内存越界
内存泄漏:会产生泄漏的内存就是堆上的内存(这里不讨论资源或句柄等泄漏情况),也就是说由
malloc 系列函数或new 操作符分配的内存。如果用完之后没有及时free 或delete,这块内存
就无法释放,直到整个程序终止。
malloc 是一个函数,专门用来从堆上分配内存。
使用malloc函数同样要注意这点:如果所申请的内存块大于目前堆上剩余内存块(整块),则内存分配会失败,函数返回NULL。注意这里说的“堆上剩余内存块”不是所有剩余内存块之和,因为malloc 函数申请的是连续的一块内存。既然malloc 函数申请内存有不成功的可能,那我们在使用指向这块内存的指针时,必须用if(NULL != p)语句来验证内存确实分配成功了
free(p):斩断指针变量与这块内存的关系。我们可以说malloc 函数分配的内存块是属于p 的,因为我们对这块内存的访问都需要通过p 来进行。free 函数就是把这块内存和p 之间的所有关系斩断。从此p 和那块内存之间再无瓜葛。至于指针变量p 本身保存的地址并没有改变,
但是它对这个地址处的那块内存却已经没有所有权了。那块被释放的内存里面保存的值也
没有改变,只是再也没有办法使用了。
内存释放之后:既然使用free 函数之后指针变量p 本身保存的地址并没有改变,那我们就需要重新把p的值变为NULL
return 语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结
束时被自动销毁