关于对C++不支持自动垃圾回收的探讨

总所周知,C++是一个不支持垃圾自动回收的编程语言,在实际编程中C++常常因为内存泄漏而引发的问题不在少数。但这真的是C++的缺点吗?
  首先,我们来看看Java的自动垃圾回收。Java使用多线程技术,在后台有一垃圾回收线程,有最低的中断值,因此只能在其他线程休息时才开始执行。但它并不是在其他线程休息时就一定能执行,激发它执行的有两个条件:一是程序可分配内存达到最大值,可能是系统内存资源不足等情况,此时垃圾回收线程才被激活;二是代码中执行 System.gc() 函数,而执行这个函数并不代表开始内存回收了,而是通知Java虚拟机准备开始内存回收。
  C#的托管垃圾回收虽然从性能上比Java要好,但任何垃圾回收机制都会存在一个内存浪费与CPU额外开销的问题。
  现在,我们来讨论一下关于C++内存泄漏的避免的问题,可以试C++程序从根本上避免内存泄漏。
  如果在一个庞大的C++程序中,如果检测出有严重的内存泄漏,如果查找所有的 new、delete 并跟踪是一种十分不明智的选择。C++是一个非常灵活的编程语言,运算符重载就是其灵活性的最佳体现。全局运算符重载甚至可以重载 new、delete 等运算符。
  下面给出 MemoryTrack.h 源代码:


#include <Windows.h>
#include <stdio.h>
#ifdef _DEBUG


//#define USE_MULTITHREADING //如果是多线程应用程序则将这句取消注释


#pragma comment(linker, "/subsystem:console")//设置编译模式为控制台程序


int iTrack = 0;//累计未释放的分配的个数


#ifdef USE_MULTITHREADING
char* cMutexName = "MemoryTrack_Test";//互斥量名称
#endif


void* operator new(unsigned int size, const char *file, int line) {//重载new运算符
#ifdef USE_MULTITHREADING
	//等待其他重载执行完毕
	HANDLE hMutex;
	do {
		hMutex = CreateMutexA(NULL, true, cMutexName);
	} while (ERROR_ALREADY_EXISTS == GetLastError());
#endif


	//设置跟踪的数据并打印数据
	printf("程序在%s文件的%d行new了一块内存。\r\n当前累计未释放的内存块有%d个。\r\n\r\n",
		file, line, ++iTrack);


#ifdef USE_MULTITHREADING
	//关闭互斥量
	ReleaseMutex(hMutex);
#endif


	//分配内存空间
	return malloc(size);
}


void operator delete(void* p) {
#ifdef USE_MULTITHREADING
	//等待其他重载执行完毕
	HANDLE hMutex;
	do {
		hMutex = CreateMutexA(NULL, true, cMutexName);
	} while (ERROR_ALREADY_EXISTS == GetLastError());
#endif


	//设置跟踪的数据并打印数据
	printf("程序delete了一块内存。\r\n当前累计未释放的内存块有%d个。\r\n\r\n", --iTrack);


	//释放内存空间
	free(p);


#ifdef USE_MULTITHREADING
	//关闭互斥量
	ReleaseMutex(hMutex);
#endif
}


void operator delete[](void* p) {
#ifdef USE_MULTITHREADING
	//等待其他重载执行完毕
	HANDLE hMutex;
	do {
		hMutex = CreateMutexA(NULL, true, cMutexName);
	} while (ERROR_ALREADY_EXISTS == GetLastError());
#endif


	//设置跟踪的数据并打印数据
	printf("程序delete了一块内存。\r\n当前累计未释放的内存块有%d个。\r\n\r\n", --iTrack);


	//释放内存空间
	free(p);


#ifdef USE_MULTITHREADING
	//关闭互斥量
	ReleaseMutex(hMutex);
#endif
}


//设置全局重载重定义,用于跟踪内存分配的位置
#define new new(__FILE__, __LINE__)


#endif


  在C++项目中,只需要在项目中引用这个头文件即可实现跟踪程序所有 new、delete 操作。另外可能导致错误的情况是头文件中具有堆变量的定义,可能在多文件项目中导致链接错误发生。此时只需要将变量声明为类静态变量并在一个.cpp文件中声明类静态变量的存储空间,即可解决这类问题。另外,这个头文件封装了多线程相关操作。如果需要检测内存泄漏的程序为多线程程序,则只需要在头文件前面加上“#define USE_MULTITHREADING”即可。


  如图所示,内存的分配与释放一目了然,在大型程序中也为内存泄漏的寻找提供了强大的方法。从效率上讲,有了运算符重载,C++不支持自动垃圾回收岂不更好?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值