程序退出后,malloc的内存会不会自动free呢?要回答这个问题,我们先要熟悉进程空间的内存相关结构.
一般编程主要只涉及进程的堆空间和栈空间(当然进程还有其他的,但初学可以不考虑).
栈空间的内存是给函数内的局部变量(包括函数参数)用的,通过函数调用和函数返回自动得分配释放(实际上只是调整栈顶指针的位置)。因为这是个“自动”的过程,所以有个额外的“栈空间溢出”的问题,主要的就是函数内局部变量不宜过大(比如int array[100*1024*1024],申请100M的内存),递归调用不要嵌套过多。
堆空间的内存简单的说就是通过malloc/new申请的,你可以选择在不再使用时释放(用free/delete),但不是必须这么做——程序退出时系统会自动回收该进程所占用的内存(僵尸进程有一点例外--它要保存进程的返回值,直到被取走才释放)。不释放内存只有两个害处:一是本进程达到能申请内存的最大值然后申请失败,导致本进程无法继续正常运行;二是本进程占用内存过多,影响系统的其他进程,或者是提高本程序运行的硬件要求。
下面的这个小例子,就是验证一下进程退出后会不会自动释放malloc的内存:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void fun( int i);
int *p;
void fun( int i)
{
p = malloc(sizeof(int));
*p = i;
printf("malloc successful,and %d has been store to the memory!\n",i);
printf("malloc the address is %x\n",p);
exit (0);
}
int main(void)
{
pid_t pid;
int k;
int status;
k = fork();
if ( k == 0)
{
fun(1);
}
else {
sleep(1);
printf("------\n");
pid = wait(&status);
printf("%x\n",p);
printf("%d\n",*p);
return 0;
}
}
|
$ ./a.out
malloc successful,and 1 has been store to the memory!
malloc the address is 804a008
------
0
Segmentation fault
看来进程退出后,malloc的内存也随之由系统自动释放了.
大多数情况下,程序浪费“有限”的内存是关系不大的。但如果某函数每被调用一次就浪费一点内存(即申请了内存,不再使用,却不释放),随着函数被调用次数的增多,浪费的内存趋于“无限”,就会产生严重的问题,即所谓“内存泄露”。“内存泄露”的存在有两个必要条件,一是程序在持续的“浪费”内存,二是
程序没有退出。所以,如果能保证程序在正常退出前浪费的内存不超过某一阈值,就可以不考虑释放内存(这也就是我们写小测试程序的情况)。
以上是内存申请了可以不释放的情况,其他情况下(比如程序需要持久运行,这也是实际中最常见的情况),申请的内存都需要释放。下面再说什么时候要申请(malloc/new)内存:
需要申请(malloc/new)内存是出于这样一种需要:栈空间是线程相关的(即栈空间的内存属于某一固定的线程),而我们有时需要线程无关即多个线程共享的内存(换个角度说,对于单线程程序,完全可以只用栈空间完成一切任务,即不用申请内存,只需把函数退出后仍需保留的变量声明在函数外面,代价就是函数参数个数的增多)。事实上,多线程比之单进程,唯一的进步也就是方便了对线程无关内存的访问,也就是可以让堆空间像多进程编程中的共享内存一样使用。
堆空间和栈空间两者之和虽然受到32位进程4G地址空间的限制,但两者之和却可相互调整:比如线程很多时可能需要增大栈空间减小堆空间,线程共享空间需求很大时则反之。
当然,c/c++有很多内存泄漏检测工具,
内存泄漏检测工具:
1.ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。
2.Dmalloc-Debug Malloc Library.
3.Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。
4.Leaky-Linux下检测内存泄漏的程序。
5.LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。
6.MEMWATCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。
7.Valgrind-Debugging and profiling Linux programs, aiming at programs written in C and C++.
8.KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree.
9.IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。
10.Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O 等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为 Microsoft Visual C++的一个插件运行。
11.Compuware DevPartner for Visual C++ BoundsChecker Suite-为C++开发者设计的运行错误检测和调试工具软件。作为Microsoft Visual Studio和C++ 6.0的一个插件运行。
12.Electric Software GlowCode-包括内存泄漏检查,code profiler,函数调用跟踪等功能。给C++和.Net开发者提供完整的错误诊断,和运行时性能分析工具包。
13.Compuware DevPartner Java Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块。
14.Quest JProbe-分析Java的内存泄漏。
15.ej-technologies JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。 JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler直觉式的GUI让你可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。4.3.2注册码:A-G666#76114F-1olm9mv1i5uuly#0126
16.BEA JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。
比如valgrind就是在Linux下查找内存泄漏和无效内存访问.具体可以参考下文:
在Linux下使用用Valgrind查找内存泄漏和无效内存访问
还有memwatch,可以参考下文
内存调试--MEMWATCH
http://blog.csdn.net/lengxingfei/archive/2006/08/09/1040800.aspx 当然,你也可以自己封装自己的malloc/free来实现内存的检测
实用小代码之内存泄漏检测
http://blog.chinaunix.net/u/18677/showart_473613.html实用小代码之内存泄漏检测(二)
http://blog.chinaunix.net/u/18677/showart_547975.html
reference:
内存泄漏(资料搜集)
http://blog.chinaunix.net/u2/78225/showart_1844866.html啥时需要申请内存和释放内存?
http://blog.chinaunix.net/u1/47120/showart_372045.html
阅读(4108) | 评论(0) | 转发(0) |