Chinaunix首页 | 论坛 | 博客
  • 博客访问: 97038
  • 博文数量: 3
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 385
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-21 12:23
个人简介

自强不息,厚德载物。

文章分类

全部博文(3)

文章存档

2016年(1)

2015年(2)

我的朋友

分类: C/C++

2015-06-29 23:39:25

一,引言

         内存泄漏是C/C++成员的梦寐,指不定就在哪个代码中就出现了。对于C/C++程序员来说,上一次程序内存泄漏的场景一定还历历在目,也许你现在正在运行的代码就会有内存泄漏,只是你没有发现而已。那么怎样能防止内存泄漏呢?我想除了不动态申请内存或者是使用像Java,C#这种自管理内存的语言,否则,谁也不敢拍着胸膛说,老子写的代码就没有内存泄漏。但是我们是有方法减少内存泄漏。

二,场景

         这还有说吗?谁都知道肯定是某个地方使用了new或者malloc, 而没有调用delete或者free来释放。 这个是最基本知识, 也是最所有内存泄漏的原因, 但是一般内存泄漏都是指热门代码执行过程的内存泄漏,就是在短时间内反复调用, 或者周期性调用的代码,这中地方的内存泄漏能立马吃光系统内存,至于,冷门代码的内存泄漏可以暂缓,比如整个程序的生命周期中只运行一次,而在这一次中泄漏了几个字节,对于应用程序来说,起不到决定性的作用。

在我们的代码中有经常会有动态申请一个内存缓冲区,典型的就是结构体,类等,使用临时的缓冲区存储数据, 进行计算, 完成之后, 释放内存。其代码一般如下:

Void fun1()

{

         // 为了篇幅,代码格式不一定正确

         struct A* a = (struct A*)malloc(sizeof(A));

         // do something

         free(a);a = null;

}

三,目标

         能不能在编译的时候就能发现上面场景的内存泄漏,有人就会说, 别和开玩笑,要是编译能解决内存泄漏问题,C/C++程序会失业的。我们就以此为目标, 看看能不能解决。

四,Solution

看到上面的这种场景,对于变量a,其生命周期也就是从申请内存到释放内存,如果在申请内存之前使用会编译错误,释放之后使用,coredump是最幸运的了。是不是想到Java或者C#常用的Guard方法, 或者是其关键字using的作用呢?如果一个C/C++程序员要向Java或者C#学习,难免有些讽刺意味,但是他们确实有很多很好解决方案是值得我们学习的,且看看javaUsing的使用方法:

usingAClass a = new AClass()

{

         // do something for a

}

using的两个大括号之外都是不能使用变量a, 我们是不是也可以是用类似的一些技术来使得1. 如果使用了new或者malloc就必须使用delete或者free,缺少就会编译错误。2. 在这之外使用我们这个变量都会编译错误。当然是可以的,我们可以利用宏+do while来解决这个问题。看看下面这两个宏, 然后我们来分析这个两个宏为什么可以解决我们上面提到的目标。

#define MEMORY_GUARD_BEGIN(type, variable)    \

do{ type* variable = (type*)malloc(sizeof(type))

#define MEMORY_GUARD_END(variable)                      \

free(variable); variable =NULL;}while(0)

看到这两个宏之后想想,对于我们第一个问题,由于有do..while的存在,只要这两个宏有一个不在同一个函数,都会编译出错, 第二个问题,由于变量的定义是在do..while中,在这之外使用都会编译出错,会报为定义的变量错误。当然在程序中还可以使用其变化方式来避免内存泄漏。

五, 弊端

 主要弊端就是不能跨函数。不能在两个宏之间将变量释放了,当然可以写一个判断。

 

阅读(2247) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~