释放内存?那要看你怎么申请的了

new->delete;malloc->free;GlobalAlloc->GlobalFree;VirtualAlloc(Ex)->VirtualFree(Ex)…

c++的用法: new delete
ansi c的用法:malloc calloc free
WIN32的用法:GlobalAlloc GlobalFree HeapAlloc HeapFree VirtualAlloc VritualFree

局部变量?
如果在堆里,自动的,如果在栈里面,就是new出来的,要自己删

你用calloc取代malloc试试。即将分配的内存块初始化为0。

Debug 某年,某月,某日。
为某一个大型程序,增加一个大型功能。编译,运行,死机。

跟踪之,居然死在了如下语句:
CString str;
而且还极不稳定,这次调试死在n行,下次调试死在m行。但都是和内存申请有关。(由于程序很大,其中频繁地申请和释放内存,多处使用new和CString)

猜测:一定是内存不够啦,遂在某处调用函数得到当前剩余的物理内存数量并使用MessageBox显示。报告曰:自由物理内存还有100多M。鼠标按下OK键,程序居然不死了。恩???

删除MessageBox()函数—死!加上MessageBox()函数—不死!再删除–死,再加上–不死。晕倒!

捏呆呆郁闷不知道多少时间后,灵光闪烁……把多处的new/delete改写为GlobalAlloc()/GlobalFree(),一切OK。

事后原因分析:使用new和CString,频繁申请,释放内存,一定产生零碎内存块。当使用MessageBox的时候,系统接管程序的运行(因为它在等待着你按OK按纽),它这时候开始回收合并这些零碎的内存块。这样程序就没有问题了。而函数GlobalAlloc()/GlobalFree()本身就有回收合并零碎内存的功能。

友情提示:在频繁使用new,CString的场合,建议把某些(大)数据块的申请用GlobalAlloc替换。

                                                   正确的使用内存

对于初学者来说,内存是个神秘的空间。程序的绝大部分错误,也是在于内存的使用不当造成的,而且这些错误有些都是隐藏很深的。所以,如何掌握内存的使用,通晓系统对内存的管理手段,将是软件成功的一个非常关键的因素。

   首先我们要了解内存的分配方式。一般来说,内存的分配方式有三种:

1.从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

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来回收的,因此将导致内存异常。

   内存是财富,正确使用财富是关键,为人如此,编程也如此。

内存申请与释放(转)相关推荐

  1. fork练习、从进程角度考虑堆区内存申请与释放的有关问题

    1.fork练习 1.1代码1; int main( int argc, char* argv[], char* envp[]) {int i = 0;for( ; i < 2; i++ ){f ...

  2. C/C++动态内存申请与释放

    20.1 理解指针的两种"改变" 普通变量(非指针,简单类 型变量)只能改变值:   1) int a = 100; 2) ... 3) a = 200;   第 1 行代码,声明 ...

  3. C/C++内存申请和释放(一)

    这一篇主要介绍一下C中的malloc和free(当然在C++中它们也可以使用),下一篇将主要介绍一下C++中的new和delete 如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢 0. mallo ...

  4. sk_buff整理笔记(三、内存申请和释放)

    承接上一篇blog--sk_buff整理笔记(二.操作函数),这篇是要来讲解下sk_buff结构的内存申请和释放函数.因为sk_buff结构是比较复杂的(并不是其本身结构复杂,而是其所指的数据区以及分 ...

  5. malloc的内存申请和释放

    一.malloc malloc是个库函数,使用时要包含<stdlib.h>这个头文件  malloc向内存申请空间时需要我们指定所需内存的大小,并且申请成功时,返回指向所申请的内存空间的指 ...

  6. 结构体变量内存申请与释放

    目录 1.前言 2.常见结构类型 3.Demo 4.结束 1.前言 结构体是C.C++开发中不可或缺的数据结构,往往涉及到函数的入参以及出参等,也必然涉及到参数的初始化.对于字符串往往是需要在堆上开辟 ...

  7. C++之内存管理:申请与释放

    目录 前言 1.C/C++内存分布 1.1虚拟内存分段 1.2理解一些概念 1.2.1栈帧向下增长 1.2.2堆向上生长 1.2.3栈和堆会碰撞吗? 1.2.4关于const的说明 2.C语言中动态内 ...

  8. linux 用户进程结束后 malloc申请的内存会自动释放吗,进程退出后malloc的内存是否会被释放?

    当一个进程退出后,不管是正常退出或者是异常退出,操作系统都会释放这个进程的资源.包括这个进程分配的内存,打开的文件等等. 内存泄露的前提是进程一直在运行:进程一旦退出,所占的整个虚拟内存都被销毁,所有 ...

  9. 内存资源的申请与释放(CC++)

    在嵌入式系统中动态内存申请存在比一般系统编程时更严格的要求,这是因为嵌入式系统的内存空间往往是十分有限的,不经意的内存泄露会很快导致系统的崩溃. 所以一定要保证你的malloc和free成对出现,如果 ...

最新文章

  1. 随机森林(Random Forest)和梯度提升树(GBDT)有什么区别?
  2. 不让复制是不可能的----js获取选中文字
  3. 从强提醒说起——社交场景下的万有“隐力”
  4. winrar皮肤的更换
  5. 公务员注册账号,密码
  6. iOS UIWebView加载网页、文件、HTML
  7. 包含对流环热,热流边界,等温边界的稳态热传导方程的FEM求解。
  8. Serverless 架构就不要服务器了?
  9. MVC3和MVC4内置Razor引擎的差异
  10. 热门Ruby 库中存在严重的命令注入漏洞
  11. HDU 5908 Abelian Period 可以直接用multiset
  12. DescribingDesign Patterns 描述设计模式
  13. latex加下划线_Latex学习系列之粗体、斜体和下划线
  14. WIFI WDS不同应用模式简介
  15. 安卓iccid_普通人也可以做码农?安卓手机上这些代码你也可以用
  16. 【Adobe】Photoshop :Mac 系统 Photoshop 软件更换许可指引
  17. 基于Opensips+Rtpengine+Freeswitch实现的网络电话系统
  18. r5 5600H 怎么样 相当于什么水平
  19. Python —对象的浅拷贝和深拷贝
  20. 厦门考计算机竞赛保送北大清华名单,厦门这所学校130人获清华北大等名校保送资格...

热门文章

  1. asp.nett网站发布过程
  2. 2022年广东省安全员A证第三批(主要负责人)考试题模拟考试题库模拟考试平台操作
  3. codeforces(E. Carrots for Rabbits)贪心
  4. 第一天前端学习的内容和心得
  5. 医保基金稽查案件管理系统丨陀螺研究院×FISCO BCOS案例专辑
  6. 冯氏竟是司马迁的后裔!冯氏历史上还出过哪些战功赫赫的大将军?
  7. 360无线升级服务器密码,360wifi扩展器默认密码_管理员密码是什么?-192路由网
  8. SQL Server高级子查询
  9. signature=b8b7708fbcb2dc05aab2f56dfec583f5,ゲームアップデート内容
  10. 中标麒麟桌面版系统(V7.0)安装教程