c语言内存泄露
① 内存泄漏有哪些
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存泄漏缺陷具有隐蔽性、积累性的特征,比其他内存非法访问错误更难检测。因为内存泄漏的产生原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷。此外,内存泄漏通常不会直接产生可观察的错误症状,而是逐渐积累,降低系统整体性能,极端的情况下可能使系统崩溃。
随着计算机应用需求的日益增加,应用程序的设计与开发也相应的日趋复杂,开发人员在程序实现的过程中处理的变量也大量增加,如何有效进行内存分配和释放,防止内存泄漏的问题变得越来越突出。例如服务器应用软件,需要长时间的运行,不断的处理由客户端发来的请求,如果没有有效的内存管理,每处理一次请求信息就有一定的内存泄漏。这样不仅影响到服务器的性能,还可能造成整个系统的崩溃。因此,内存管理成为软件设计开发人员在设计中考虑的主要方面[1] 。
泄漏原因
在c语言中,从变量存在的时间生命周期角度上,把变量分为静态存储变量和动态存储变量两类。静态存储变量是指在程序运行期间分配了固定存储空间的变量而动态存储变量是指在程序运行期间根据实际需要进行动态地分配存储空间的变量。在内存中供用户使用的内存空间分为三部分:
程序存储区
静态存储区
动态存储区
程序中所用的数据分别存放在静态存储区和动态存储区中。静态存储区数据在程序的开始就分配好内存区,在整个程序执行过程中它们所占的存储单元是固定的,在程序结束时就释放,因此静态存储区数据一般为全局变量。动态存储区数据则是在程序执行过程中根据需要动态分配和动态释放的存储单元,动态存储区数据有三类函数形参变量、局部变量和函数调用时的现场保护与返回地址。由于动态存储变量可以根据函数调用的需要,动态地分配和释放存储空间,大大提高了内存的使用效率,使得动态存储变量在程序中被广泛使用。
② 在Linux中运行的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. Leak
Monitor-一个Firefox扩展,能找出跟Firefox相关的泄漏类型。
10. IE Leak Detector
(Drip/IE Sieve)-Drip和IE Sieve leak
detectors帮助网页开发员提升动态网页性能通过报告可避免的因为IE局限的内存泄漏。
11. Windows Leaks
Detector-探测任何Win32应用程序中的任何资源泄漏(内存,句柄等),基于Win API调用钩子。
12. SAP Memory
Analyzer-是一款开源的JAVA内存分析软件,可用于辅助查找JAVA程序的内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse
RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。
13. DTrace-即动态跟踪Dynamic
Tracing,是一款开源软件,能在Unix类似平台运行,用户能够动态检测操作系统内核和用户进程,以更精确地掌握系统的资源使用状况,提高系统性能,减少支持成本,并进行有效的调节。
14. IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus
将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。
15. Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为Microsoft
Visual C++的一个插件运行。
16. Compuware DevPartner for Visual C++ BoundsChecker
Suite-为C++开发者设计的运行错误检测和调试工具软件。作为Microsoft Visual Studio和C++ 6.0的一个插件运行。
17. Electric Software GlowCode-包括内存泄漏检查,code
profiler,函数调用跟踪等功能。给C++和.Net开发者提供完整的错误诊断,和运行时性能分析工具包。
18. Compuware DevPartner Java
Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块。
19. Quest JProbe-分析Java的内存泄漏。
20. ej-technologies JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler直觉式的GUI让你可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。4.3.2注册码:A-G666#76114F-1olm9mv1i5uuly#0126
21. BEA JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。
22. SciTech Software AB .NET Memory
Profiler-找到内存泄漏并优化内存使用针对C#,VB.Net,或其它.Net程序。
23. YourKit .NET & Java Profiler-业界领先的Java和.NET程序性能分析工具。
24. AutomatedQA AQTime-AutomatedQA的获奖产品performance profiling和memory
debugging工具集的下一代替换产品,支持Microsoft, Borland, Intel, Compaq 和
GNU编译器。可以为.NET和Windows程序生成全面细致的报告,从而帮助您轻松隔离并排除代码中含有的性能问题和内存/资源泄露问题。支持.Net
1.0,1.1,2.0,3.0和Windows 32/64位应用程序。
25. JavaScript Memory Leak Detector-微软全球产品开发欧洲团队(Global Proct
Development- Europe team, GPDE)
发布的一款调试工具,用来探测JavaScript代码中的内存泄漏,运行为IE系列的一个插件。
③ c语言内存泄露如何解决
确保每个malloc()函数申请的空间,都有对应的free()函数将其释放。这是基本的办法。另外,要避免在malloc()与对应free()之间的语句,不出现严重错误,导致系统中断。
④ 一个关于C语言程序内存泄露的问题:
malloc是向系统申请内存的,因为你用的系统在你的程序退出后自动释放的内存,所以没有造成泄露问题。
这种情况下,你的程序不退出,而是不断地申请内存,部分释放内存或完全不释放内存,才会造成泄露。
⑤ C语言中的内存泄露 怎样避免与检测
堆经常会出现两种类型的问题:1.释放或改写仍在使用的内存(称为:“内存损坏”)。2.未释放不再使用的内存(称为:“内存泄露”)。这是最难被调试发现的问题之一
有些程序并不需要管理它们的动态内存的使用。当需要内存时,它们简单地通过分配来获得,从来不用担心如何释放它。这类程序包括编译器和其他一些运行一段固定的(或有限的)时间然后终止的程序。当这种类型的程序终止时,所有内存会被自动回收。细心查验每块内存是否需要回收纯属浪费时间,因为它们不会再被使用。
其他程序的生存时间要长一点。有些工具如日历管理器、邮件工具以及操作系统本事经常需要数日及至数周连续运行,并需要管理动态内存的分配和回收。由于C语言通常并不使用垃圾回收器(自动确认并回收不再使用的内存块),这些C程序在使用malloc()和free()时不得不非常慎重。
堆经常会出现两种类型的问题:
1.释放或改写仍在使用的内存(称为:“内存损坏”)。
2.未释放不再使用的内存(称为:“内存泄露”)。
这是最难被调试发现的问题之一。如果每次已分配的内存块不再使用而程序并不释放它们,进程就会一边分配越来越多的内存,一边却并不释放不再使用的那部分内存。
避免内存泄露
每当调用malloc分配内存时,注意在以后要调用相应的free来释放它。
如果不知道如何调用free与先前的malloc相对应,那么很可能已经造成了内存泄露!
一种简单的方法就是在可能的时候使用alloca()来分配动态内存,以避免上述情况。当离开调用alloca的函数时,它所分配的内存会被自动释放。
显然,这并不适用于那些比创建它们的函数生命期更长的结构。但如果对象的生命期在该函数结束前便已经终止,这种建立在堆栈上的动态内存分配是一种开销很小的选择。有些人不提倡使用alloca,因为它并不是以后总可移植的方法。如果处理器在硬件上不支持堆栈,alloca()就很难高效地实现。
我们使用“内存泄露”这个词是因为一种稀有的资源正在被一个进程榨干。内存泄露的主要可见症状就是罪魁进程的速度很减慢。原因是体积大的进程更有可能被系统换出,让别的进程运行,而且大的进程在换进换出时花费的时间也更多。即使泄露的内存本省并不被引用,但它仍用可能存在于页面中(内容自然是垃圾),这样就增加了进程的工作页数量,降低了性能。另外需要注意的一点是,内存泄露往往比忘记释放的的数据结构要打,因为malloc()所分配的内存通常会圆整为下一个大于申请数量的2的整数次方(如申请212B,会圆整为256B)。在资源有限的情况下,即使引起内存泄露的进程并不运行,整个系统运行速度也会被拖慢。从理论上说,进程的大小有一个上限值,这在不同的操作系统中各不相同。在当前的SunOS版本中,进程的最大地址空间可以多达4GB。事实上,在进程所泄露的内存远未达到这个数量时,磁盘的交换区早已消耗殆尽。
如何检测内存泄露
观察内存泄露是一个两步骤的过程。首先,使用swap命令观察还有多少可用的交换空间:
/usr/sbin/swap -s
total:17228K bytes allocated + 5396K reserved=22626K used,29548K available.
在一两分钟内键入该命令三到四次,看看可用的交换区是否在减少。还可以使用其他一些/usr/bin/*stat工具如netstat、vmstat等。如发现波段有内存被分配且从不释放,一个可能的解释就是有个进程出现了内存泄露。
⑥ 哪些情况会内存泄漏
1、资源释放问题
。 Android 程序代码的问题,长期保持某些资源,如 Context、Cursor、IO 流的引用,资源得不到释放造成内存泄露。
2、对象内存过大问题
保存了多个耗用内存过大的对象(如 Bitmap、XML 文件),造成内存超出限制。
3、static 关键字的使用问题
static 是 Java 中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。所 以用 static 修饰的变量,它的生命周期是很长的,如果用它来引用一些资源耗费过多的实例(Context 的情况最 多),这时就要谨慎对待了。
public class ClassName { private static Context mContext; //省略 }
1
1
以上的代码是很危险的,如果将 Activity 赋值到 mContext 的话。那么即使该 Activity 已经 onDestroy,但是由 于仍有对象保存它的引用,因此该 Activity 依然不会被释放。
我们举 Android 文档中的一个例子。
private static Drawable sBackground;
@Override protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this); //getApplicationContext label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground); setContentView(label);
}
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
sBackground 是一个静态的变量,但是我们发现,我们并没有显式的保存 Context 的引用,但是,当 Drawable 与 View 连接之后,Drawable 就将 View 设置为一个回调,由于 View 中是包含 Context 的引用的,所以,实际 上我们依然保存了 Context 的引用。这个引用链如下: Drawable->TextView->Context 所以,最终该 Context 也没有得到释放,发生了内存泄露。
针对 static 的解决方案
① 应该尽量避免 static 成员变量引用资源耗费过多的实例,比如 Context。
② Context 尽量使用 ApplicationContext,因为 Application 的 Context 的生命周期比较长,引用它不会 出现内存泄露的问题。 ③ 使用 WeakReference 代替强引用。比如可以使用 WeakReference mContextRef;
4、线程导致内存溢出
线程产生内存泄露的主要原因在于线程生命周期的不可控。我们来考虑下面一段代码。
。
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
private class MyThread extends Thread{
@Override
public void run() {
super.run(); //do somthing while(true)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
这段代码很平常也很简单,是我们经常使用的形式。我们思考一个问题:假设 MyThread 的 run 函数是一个很费 时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,一 般情况下当屏幕转换时会重新创建 Activity,按照我 们的想法,老的 Activity 应该会被销毁才对,然而事实上并非如此。 由于我们的线程是 Activity 的内部类,所以 MyThread 中保存了 Activity 的一个引用,当 MyThread 的 run 函 数没有结束时,MyThread 是不会被销毁的,因此它所引用的老的 Activity 也不会被销毁,因此就出现了内存泄露的 问题。有些人喜欢用 Android 提供的 AsyncTask,但事实上 AsyncTask 的问题更加严重,Thread 只有在 run 函数不结 束时才出现这种内存泄露问题,然而 AsyncTask 内部的实现机制是运用了 ThreadPoolExcutor,该类产生的 Thread 对 象的生命周期是不确定的,是应用程序无法控制的,因此如果 AsyncTask 作为 Activity 的内部类,就更容易出现内存 泄露的问题。
针对这种线程导致的内存泄露问题的解决方案:
第一、将线程的内部类,改为静态内部类(因为非静态内部类拥有外部类对象的强引用,而静态类则不拥有)。
第二、在线程内部采用弱引用保存 Context 引用。
⑦ C语言指针 内存泄漏
for (i=0;i<10;i++)
{
char *p=(char *)malloc(nSize *sizeof(char));
i++;
}
调用了10次malloc,就分配了10份空间,每次循环,你之前分配空间的地址都会被新一次分配的地址覆盖,继而丢失了。
最后你只是释放了一次,也就是9次都丢失了,造成内存泄露
⑧ c语言内存泄漏如何定位
用gstack长期观察函数调用栈,分析调用情况与内存增长的关系,找到与内存泄露相关的函数,重点分析。
C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。
尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。
C语言是一门面向过程的计算机编程语言,与C++、C#、Java等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
C语言描述问题比汇编语言迅速、工作量小、可读性好、易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编语言代码生成的目标程序效率低10%-20%。因此,C语言可以编写系统软件。
⑨ c语言中string重新赋值会不会出现内存泄露
"sfdfsa"和"fwinfg",两者都是字符串常量,既不是在栈上,也不是在堆上。在C/C++语言中常量被分配在常量存储区(数据段)上,由系统控制。因为没有涉及到堆/动态内存,所以不存在所谓内存泄露的问题。
以下是内存泄漏的定义
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
⑩ 写C语言程序,内存泄漏怎么办,重启电脑可以吗
不用重启。
内存泄漏是程序出问题了。可能是数组访问越界之类的问题。
关闭程序即可,如果再次启动还是这个问题,请发送源代码来追问。