⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xielou.txt

📁 Q: 我应该怎样处理内存泄漏? A: 很简单
💻 TXT
字号:
Q: 我应该怎样处理内存泄漏?
A: 很简单,只要写“不漏”的代码就完事了啊。显然,如果你的代码到处是new、delete、指针运算,那你想让它“不漏”都难。不管你有多么小心谨慎,君为人,非神也,错误在所难免。最终你会被自己越来越复杂的代码逼疯的——你将投身于与内存泄漏的奋斗之中,对bug们不离不弃,直至山峰没有棱角,地球不再转动。而能让你避免这样困境的技巧也不复杂:你只要倚重隐含在幕后的分配机制——构造和析构,让C++的强大的类系统来助你一臂之力就OK了。标准库中的那些容器就是很好的实例。它们让你不必化费大量的时间精力也能轻松惬意地管理内存。我们来看看下面的示例代码——设想一下,如果没有了string和vector,世界将会怎样?如果不用它们,你能第一次就写出毫无内存错误的同样功能代码吗?

	#include<vector>
	#include<string>
	#include<iostream>
	#include<algorithm>
	using namespace std;

	int main()	// small program messing around with strings
	{
		cout << "enter some whitespace-separated words:\n";
		vector<string> v;
		string s;
		while (cin>>s) v.push_back(s);

		sort(v.begin(),v.end());

		string cat;
		typedef vector<string>::const_iterator Iter;
		for (Iter p = v.begin(); p!=v.end(); ++p) cat += *p+"+";
		cout << cat << '\n';
	}

请注意这里没有显式的内存管理代码。没有宏,没有类型转换,没有溢出检测,没有强制的大小限制,也没有指针。如果使用function object和标准算法[译注:指标准库中提供的泛型算法],我连Iterator也可以不用。不过这毕竟只是一个小程序,杀鸡焉用牛刀?

当然,这些方法也并非无懈可击,而且说起来容易做起来难,要系统地使用它们也并不总是很简单。不过,无论如何,它们的广泛适用性令人惊讶,而且通过移去大量的显式内存分配/释放代码,它们确实增强了代码的可读性和可管理性。早在 1981年,我就指出通过大幅度减少需要显式加以管理的对象数量,使用C++“将事情做对”将不再是一件极其费神的艰巨任务。

如果你的应用领域没有能在内存管理方面助你一臂之力的类库,那么如果你还想让你的软件开发变得既快捷又能轻松得到正确结果,最好是先建立这样一个库。

如果你无法让内存分配和释放成为对象的“自然行为”,那么至少你可以通过使用资源句柄来尽量避免内存泄漏。这里是一个示例:假设你需要从函数返回一个对象,这个对象是在自由内存堆上分配的;你可能会忘记释放那个对象——毕竟我们无法通过检查指针来确定其指向的对象是否需要被释放,我们也无法得知谁应该负责释放它。那么,就用资源句柄吧。比如,标准库中的auto_ptr就可以帮助澄清:“释放对象”责任究竟在谁。我们来看:

	#include<memory>
	#include<iostream>
	using namespace std;

	struct S {
		S() { cout << "make an S\n"; }
		~S() { cout << "destroy an S\n"; }
		S(const S&) { cout << "copy initialize an S\n"; }
		S& operator=(const S&) { cout << "copy assign an S\n"; }
	};

	S* f()
	{
		return new S;	// who is responsible for deleting this S?
	};

	auto_ptr<S> g()
	{
		return auto_ptr< S >(new S);	// explicitly transfer responsibility for deleting this S
	}

	int main()
	{
		cout << "start main\n";
		S* p = f();
		cout << "after f() before g()\n";
	//	S* q = g();	// caught by compiler
		auto_ptr< S > q = g();
		cout << "exit main\n";
		// leaks *p
		// implicitly deletes *q
	}

这里只是内存资源管理的例子;至于其它类型的资源管理,可以如法炮制。

如果在你的开发环境中无法系统地使用这种方法(比方说,你使用了第三方提供的古董代码,或者远古“穴居人”参与了你的项目开发),那么你在开发过程中可千万要记住使用内存防漏检测程序,或者干脆使用垃圾收集器(Garbage Collector)。 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -