对于初学者来说,内存是个神秘的空间。程序的绝大部分错误,也是在于内存的使用不当造成的,而且这些错误有些都是隐藏很深的。所以,如何掌握内存的使用,通晓系统对内存的管理手段,将是软件成功的一个非常关键的因素。
首先我们要了解内存的分配方式。一般来说,内存的分配方式有三种:
1.从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
2.在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
3.从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
以上三种分配方式,我们要注意内存生命期的问题:
1.静态分配的区域的生命期是整个软件运行期,就是说从软件运行开始到软件终止退出。只有软件终止运行后,这块内存才会被系统回收
2.在栈中分配的空间的生命期与这个变量所在的函数和类相关。如果是函数中定义的局部变量,那么它的生命期就是函数被调用时,如果函数运行结束,那么这块内存就会被回收。如果是类中的成员变量,则它的生命期与类实例的生命期相同
3.在堆上分配的内存,生命期是从调用new或者malloc开始,到调用delete或者free结束。如果不掉用delete或者free。则这块空间必须到软件运行结束后才能被系统回收。
下面我们再看看,在使用内存的过程中,我们经常发生一些什么样的错误。以及我们应该采取哪些对策。
发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户怒气冲冲地把你找来,程序却没有发生任何问题,你一走,错误又发作了。
常见的内存错误及其对策如下:
1 内存分配未成功,却使用了它。
编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。
2 内存分配虽然成功,但是尚未初始化就引用它。
犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。
内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。
3 内存分配成功并且已经初始化,但操作越过了内存的边界。
例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。
4 忘记了释放内存,造成内存泄露。
含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。
动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。
5 释放了内存却继续使用它。
有三种情况:
(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。
(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。
综上所述,我们应该注意:
1.用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。
2.不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
3.避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
4.动态内存的申请与释放必须配对,防止内存泄漏。
5.用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。
下面举几个经典的错误例子,大家不要犯同样的错误:
1. 返回栈内存指针
char *GetString(void)
{
char *p = "hello world";
return p;
}
char* pGet = GetString();
这段程序编译时没有错误,运行也没有错误,但是你却无法使得返回的pGet指针指向的数据是你想要的“hello world”,因为指针p的生命期是函数GetString内,运行完函数GetString后,p分配的栈空间马上被系统回收了。虽然pGet指向了p当初分配的内存地址,但是那块地址已经没有内容了。
2.这是一个出现频率非常高的错误
char* pChar = new char;
……
int a ;
pChar = &a;
……
delete pChar;
当然这是一个例子,具体的程序各有不同。
这段程序有两个问题。一是pChar = &a;将导致pChar原先分配的空间无法再被获取,就象我们的丢失了朋友的电话号码一样,无法再联系这个朋友了。这就造成了内存泄漏。如果内存泄漏多了,可能导致系统的崩溃,因为可用的资源将越来越少,直到枯竭为止。第二个问题是delete pChar将导致异常发生,因为这时的pChar已经不是指向动态分配的内存了,而是指向了a分配的栈空间,而栈空间是不能使用delete来回收的,因此将导致内存异常。
内存是财富,正确使用财富是关键,为人如此,编程也如此。
分享到:
相关推荐
对于初学者来说,内存是个神秘的...程序的绝大部分错误,也是在于内存的使用不当造成的,而且这些错误有些都是隐藏很深的。所以,如何掌握内存的使用,通晓系统对内存的管理手段,将是软件成功的一个非常关键的因素。
Handler对象中使用匿名内部类或非静态内部类正确地释放消息避免内存泄漏或增加Native内存,在Android中,Handler对象通常会被用来在主线程(UI线程)中处理消息,以更新UI界面。当我们在Handler对象中使用匿名内部类...
正确使用 RamDisk Plus 的方法解决分配内存后占用系统内存的问题
如何正确查看Linux机器内存使用情况.docx如何正确查看Linux机器内存使用情况.docx
文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...
在计算机科学中,内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。。。。
买了一根8GB金士顿内存条,装上发现原来32bit Win7 32位系统最多支持3.25GB内存... 亲自尝试了一下,耗时1小时,感觉内存用量到达90%时,系统仍然健步如飞,猜想是因为虚拟内存比以前使用C盘做虚拟内存要给力多了。
memwatch内存检测工具,配置相应的预处理器,运行后会生成Libmem文件,提示程序中相应的内存泄露说明
WIN7系统下正确设置RAMDISK软件利用系统未识别内存
C++ 如何正确的使用线程 释放线程资源 魔鬼作坊学游戏辅助制作 moguizuofang.com
RamSmash是一款让你以正确的方式来维护和管理内存的工具。RamSmash能释放未有效利用的内存,并把它转变成有效的资源。通过优化内存的使用,你电脑将会以平衡的速度运转并且不会将内存消尽。它非常易于使用,完全兼容...
VC使用CRT调试功能来检测内存泄漏 C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:“最大的长处也可能成为最大的弱点”,那么 C/C++ 应用程序正好印证了这句话。在 C/C++ 应用程序...
C 库函数 - malloc() 函数简介 函数的声明 介绍一下用法 malloc的实现机制 虚拟内存地址与物理内存地址 ...正确使用malloc函数分配内存 正确使用free函数释放内存 自定义一套内存分配器 最后
程序需要一块内存用以储存数据时,就需要使用操作系统提供的「功能函数」来申请,如果内存分配成功,函数就会将所新开辟的内存区地址返回给应用程序,应用程序就可以通过这个地址使用这块内存。这就是「动态内存分配...
ST官方对STM32使用LWIP的配置说明。 LwIP 在 lwipopts.h 和 opt.h 头文件中提供了多个配置选项。用户可以根据不同的性能需求和不同应用的内存限制对协议栈用 到的内存配置进行调节。Opt.h 头文件中包括协议使能和...
文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...
介绍algrind的安装与使用方法,通过对内存错误的各种出错信息的认识,帮助使用者正确使用valgrind工具。是在ubuntu上编辑的,请在ubuntu上打开 参考:https://blog.csdn.net/u012662731/article/details/78652651 ...
Nohang 一个高度可配置的Linux守护程序,能够正确防止内存不足的情况
**`内存泄漏`**是当程序不正确地进行内存管理时出现的一种资源泄漏,表现为程序不再需要使用的内存空间并没有及时被释放掉。内存泄漏并非指物理内存的消失,而是在程序分配了某段内存后,由于设计错误,失去了对该段...
但是根据我的经验, 有很多情况下, Windows XP不能够正确的识别出4GB内存. 一般这都是因为计算机硬件占用内存. 32-bit的 Windows XP 默认不能使用4GB内存: 32位的Windows XP最大支持4GB物理内存. 但是Windows XP不能...