中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > C/C++
C/C++的Garbage Collection的使用
作者:未知 时间:2005-09-13 19:19 出处:ChinaUnix.net 责编:chinaitpower
              摘要:C/C++的Garbage Collection的使用

这里展示如何使用 Garbage Collector for C and C++,只限于linux平台

DISCLAIMER: 这里的内容是我个人学习的体会, 你可以在你的任何程序中使用这里的技术.我不对使用这种方法造成的后果负责,我相信你可以正确的用你自己的方法编写程序.

使用GC的意义:
C语言的程序经常要动态的申请内存,如果申请到的内存没有用free()释放,只有到程序退出时才会由操作系统释放所申请的内存. 这对于很短暂运行的程序,比如ls命令,无论如何不是大问题. 但是我们写的一些internet服务程序可能会长期运行,那些没有释放的内存随时间的推移越来越多,结果程序就失败了.

GC功能就是程序中回收那些泄漏内存的功能,在java,lisp,python等语言都有,我们C/C++语言的爱好者不能让它们嘲笑我们没有这些功能吧,而且GC会使我们的程序更强壮.所以知道我们拥有这个工具还是挺不错的.

首先到 http://www.hpl.hp.com/personal/Hans_Boehm/gc/网站下载软件,包名字为 gc.tar.gz

然后安装:
cd ~ 进入自己的HOME目录
解包 tar xvzf gc.tar.gz 在~/gc6.1下解包, 假定版本是6.1,其它版本类似
编译 cd gc6.1 
./configure
make
make check 如果这里显示 gc 不工作,你就不好运了.google一下其它的包吧.
用root身分安装:
su 输入root帐户密码
make install 默认的库安装在 /usr/local/lib目录下
下面更新库搜索路径 
cd /etc
编辑 ld.so.conf, 结尾加一句 /usr/local/lib
运行 /sbin/ldconfig 
exit 退出root帐户

好了, 下面看看我们怎么使用吧.
一. 把头文件放到自己方便的地方,或者每次包括 "~/gc6.1/include/gc.h"
二. 连接GC库: 动态的连接 gcc a.cpp -lgc -ldl 使用libgc.so, libdl.so两个库
                静态的连接 gcc a.cpp /usr/local/lib/libgc.a -lpthread 使用libpthread.so
    静态连接的好处是可以拷贝到类似的系统中用,比如另外一台标准安装的Redhat 8.0,而不用在那台机器上安装GC库.

一些示范的用法:

1. 把GC作为内存泄漏的检测工具, 方法如下:

   #include "../gc6.1/include/leak_detector.h"
[code:1:d280d64dd4]
int main() 
{
int *p[10];
int i;
GC_find_leak = 1; //如果去掉这一句,就变成了标准的GC功能,这一句使它按内存检测方式运行

for (i = 0; i < 10; ++i) {
p[i] = (int*)malloc(sizeof(int)+i);
}
        for (i = 2; i < 10; ++i) {
free(p[i]);
}
for (i = 0; i < 9; ++i) {
p[i] = (int*)malloc(sizeof(int)+i);
}
        CHECK_LEAKS(); //标准GC不需要这一句,这里强制GC_gcollect();
}
[/code:1:d280d64dd4]
编译运行如下:
gcc a.c -lgc -ldl 或者 gcc a.c libgc.a -lpthread
./a.out
显示:
Leaked composite object at 0x805bff0 (b.c:10, sz=5)

Leaked composite object at 0x805afe8 (b.c:10, sz=4)

当我们调试结束后,可以把检测去掉就可以了.

2.一个更有意义的做法是,我们使用标准GC的功能,那么我们根本不用释放申请的内存,不用时就忘掉它好了.

#include "../gc6.1/include/gc.h"
#define malloc(n) GC_malloc(n) //这样可以方便的使用而不改程序中原有的malloc
[code:1:d280d64dd4]
#include <stdio.h>

int main()
{
        int i;
char *p;
        for (i = 0; i < 10000; ++i) {
                p = malloc(100000*sizeof(int)); //malloc许多次,没有free
if(p==0) {printf("No memory\n");exit(1);}
        }
}
[/code:1:d280d64dd4]
编译 gcc b.c -lgc -ldl 或者 gcc b.c /usr/local/lib/libgc.a -lpthread
./a.out &
  看看吧, 不会把内存用光的.不会显示No memory信息.

3. 在C++中也是可以使用的. 
方法一: 替换调原来的malloc库函数:
      在g++中, C++的new和delete是通过调用malloc实现内存分配的,我们可以直接替换掉malloc函数.
[code:1:d280d64dd4]
#include <iostream>
using namespace std;
#include <cstdlib>
#include "gc6.1/include/gc.h"

//override malloc library
void *malloc(size_t size) {
return GC_malloc(size);
}
void free(void* ptr)
{
return GC_free(ptr);
}


int main() {

   while(1)
             char *p = new char[10000];
   return 0;
}
[/code:1:d280d64dd4]
方法二: 也可以重载全局的new,delete. 这样只是用new分配才有GC功能,不影响malloc
[code:1:d280d64dd4]
#include <stdio.h>
#include <stdlib.h>
#include "gc6.1/include/gc.h"

void* operator new(size_t sz) {
  void* m = GC_malloc(sz);
  if(!m) puts("out of memory");
  return m;
}

void operator delete(void* m) {
  GC_free(m);
}

main() {
  while(1)
          int *p = new int[10000]; //test GC
}
[/code:1:d280d64dd4]
方法三. 在gc6.1/include/gc_cpp.h中有一个 class gc {...},继承这个类也可以. 不过我不太喜欢这个方法.

C++中使用GC的问题:
1. 同java是一样的,析构函数要仔细考虑. 使用的GC后,我们一般不在用delete,那么析构函数根本不会调用.

   a. 假如我们的析构函数是重要的,必须被调用. 那么我们只可以使用这个类的全局的对象, local的对象,或者用new分配的对象而且保证调用delete,即我们保证不使用GC的功能.

   b. 假如析构函数是默认的, 即编译器合成的而我们不一定要它被调用,这样的类可以随便使用,也可以用new分配而不delete. 这时我们必须自己手动释放内存以外的其它资源.

2. 程序会由于GC变慢,并且什么时候变慢不知道,不适合实时的应用.

3. 按Stroustrap的说法,不一定需要使用GC. 我们可以灵活的使用string,vector模板,避免malloc,new就行了.

 无双 回复于:2003-03-12 13:38:14
很不错
希望大家也能把自己学习中的经验写出来

 问号 回复于:2003-03-13 14:06:22
2.一个更有意义的做法是,我们使用标准GC的功能,那么我们根本不用释放申请的内存,不用时就忘掉它好了.

#include "../gc6.1/include/gc.h"
#define malloc(n) GC_malloc(n) //这样可以方便的使用而不改程序中原有的malloc

编译 gcc b.c -lgc -ldl 或者 gcc b.c /usr/local/lib/libgc.a -lpthread
./a.out &
看看吧, 不会把内存用光的.不会显示No memory信息. 

我使用了,但是发现我使用free,程序就会出错sigsegv,停留在free这里,难道使用了GC就不需要原来的free了么.

 无双 回复于:2003-03-13 18:45:25
应该是吧

GC就像是JAVA
就只管申请

不管释放


释放已由库自动完成

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有