假设我在C ++类中有以下构造函数:
MyClass::MyClass()
{
char* buffer = malloc(100);
if (0 != someD3DXCallThatCanFail(..., buffer, ...))
{
free(buffer);
throw MyException(L"some message");
}
char* buffer2 = malloc(200);
if (0 != anotherD3DCallThatCanFail(..., buffer2, ...))
{
free(buffer);
free(buffer2);
throw MyException(L"another message");
}
.. more code here where buffer and buffer2 are still used
free(buffer);
free(buffer2);
}
编辑:我讨厌malloc / free和new / delete,但不幸的是我需要使用缓冲区来加载纹理,然后将纹理传递给ID3D10ShaderResourceView,ID3D10Buffer,顶点缓冲区等。所有这些都需要指向缓冲区的指针。
我尝试使用异常而不是返回错误代码。 我还想在需要它们的地方创建缓冲区,并在不再需要它们之后立即释放它们。
然而,看起来很难看的是,如果出现错误,无论我是否返回错误代码或抛出异常,我仍然应该记得清理到那时为止创建的任何缓冲区。如果我有10个缓冲区和10个可能的错误点,我将不得不调用free()100次(在每个错误情况下都要记得释放每个缓冲区)。
现在假设我或者更糟,我的同事想要改变一些逻辑,比如说,在中间的某处添加另一个缓冲区。现在,他必须通过方法的其余部分查看可能发生的所有错误,并在每个这样的位置为该缓冲区添加free()。如果他赶时间,他可以很容易地忽略一些这样的地方,并且你有内存泄漏。
这也极大地破坏了代码。
finally关键字可以解决Java或C#中的问题。无论代码在哪里发生异常,我仍然会在“finally”中清理所有缓冲区(顺便说一句,你不需要使用垃圾收集)。在我理解的C ++中,我可能必须为任何这样的缓冲区创建一个成员变量,并在析构函数中确保清理缓冲区。看起来对我来说也很难看,因为名为“pBuffer”的成员变量,即使是私有变量,也只是垃圾,因为它只在一个方法中使用(在本例中是构造函数),并且其余部分始终为NULL。时间。
必须是常见问题,但我无法使用搜索找到答案。谢谢!
答案 0 :(得分:8)
手动停止管理内存,您不会遇到这些问题。使用类似std::vector<char>
的内容。
或者,你可以使用Boost的shared_array
之类的东西,但这对你在这里尝试做的事情来说太过分了:
http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/shared_array.htm
这里更常见的一点是你应该使用RAII习语 - 也就是说,当你获得资源时,你将它们存储在一个类的实例中,它的析构函数再次释放它们。然后,然而,该资源拥有类的实例超出范围,保证资源被释放。
见这里:
http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
答案 1 :(得分:4)
规范的答案是“资源获取是初始化”(RAII)和智能指针的原则。您在堆栈上创建一个类实例,它将释放其析构函数中的内存,例如: boost::scoped_ptr
。
答案 2 :(得分:2)
相反,请使用raii:
MyClass::MyClass()
{
std::vector<char> buffer(100);
if (0 != someD3DXCallThatCanFail(...))
{
throw MyException(L"some message");
}
std::vector<char> buffer2c(200);
if (0 != anotherD3DCallThatCanFail(...))
{
throw MyException(L"another message");
}
.. more code here
}
答案 3 :(得分:1)
使用惯用的C ++方法:RAII。这个维基百科页面有C ++样本。
答案 4 :(得分:1)
再次搜索“C ++智能指针”。你需要在内存而不是原始malloc
上使用异常安全的包装器,正如你所指出的那样带来了很多麻烦,顺便说一下,operator new
可能会更好地替换现在你正在编写C ++而不是C代码。
上一个答案here涵盖了这一领域。
答案 5 :(得分:1)
对此的规范答案将是C ++ 11中的unique_ptr。在那之前,可能scoped_ptr
(http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/scoped_ptr.htm)单身人士和scoped_array
(http://www.boost)来自Boost的数组的.org / doc / libs / 1_47_0 / libs / smart_ptr / scoped_array.htm)。或者您可以自己编写等效代码。