博客首页 注册 建议与交流 排行榜 加入友情链接         宝宝相册的专门空间
推荐 投诉 搜索: 帮助

飞翔,嵌入式linux

linux嵌入式系统必将大行于天下。专注于linux嵌入式系统的搭键,专注于高效稳定软件的开发,专注底层程序调试技术。
  feixiang.cublog.cn

关于作者
姓名:飞翔
Email:loughsky@sina.com
职业:IT
年龄:32
位置:北京
个性介绍:专注在嵌入式操作系统,以及高效程序调试
|| << >> ||
我的分类


dlopen有可能导致内存泄漏

下面我举一个常见的例子:

 

在动态库中,我要使用进程中唯一的对象mInstance,标准的写法:

liba.so的代码

static Myclass *mInstance;     //声明一个静态Myclass对象指针。

 

Myclass getInstance()

{

     if(NULL == mInstance)

     {

           mInstance = new Myclass;

      }

      return mInstance;

}

 

上面的代码,大家应该非常熟悉了,而在引入了dlopen之后,有可能会导致内存泄漏。

 

下面,我使用伪代码来说明这个问题。

 

1                         dlopen(liba.so);

2                         pInstance=getInstance();

……………….

3                         dlclose(liba.so);

………………….

4                         dlopen(liba.so);

5                         pInstance=getInstance();

………………….

 

我来解释一下有可能导致的内存泄漏。

1、               加载了动态库liba.so,同时初始化了其数据段,这时mInstance应该为空。

2、               getInstance看到mInstance为空,则在堆中分配了一块内存,生成一个Myclass实例,同时为数据段的mInstance赋值

3、               卸载了动态库liba.so,这时mInstance是不存在的,也就意味着我们丢失了在堆中生成的Myclass对象实例。

4、               加载了动态库liba.so,同时初始化了其数据段,这时mInstance应该为空。

5、               getInstance看到mInstance为空,则在堆中又分配了一块内存,生成一个Myclass实例,同时为数据段的mInstance赋值

 

这样,每做一次这样的时间循环,将会导致一个Myclass对象内存泄漏。

 

这个问题的实质是:

在我们的心目中,一个static的对象的生存周期是贯穿在进程始终的,实际上不是这样。在动态库中的static对象,其生命周期等于该动态库的生命周期。采用静态链接的方式,动态库的生命周期等于进程的声明周期;而采用动态加载的方式,则是不同的。

 

为了避免上面的问题出现,我们要在动态库卸载的时候,释放掉该块内存。

 

有两个方法:

1、  我们写一个释放内存的函数,在调用dlclose之前,调用该函数。

2、  我们在动态库的析构函数中,释放这块内存。

  void __attribute__ ((destructor)) my_fini(void);

在这里我推荐第二个方法,它对不需要上层用户做任何改动,对其完全透明。

发表于: 2008-04-09,修改于: 2008-04-09 12:58,已浏览461次,有评论0条 推荐 投诉


网友评论
 发表评论