在C++中抛出异常时释放本地缓冲区

ise*_*all 2 c++ free buffer constructor exception

假设我在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);
}
Run Code Online (Sandbox Code Playgroud)

编辑:我讨厌malloc/free和new/delete,但不幸的是我需要使用缓冲区来加载纹理,然后将纹理传递给ID3D10ShaderResourceView,ID3D10Buffer,顶点缓冲区等.所有这些都需要指向缓冲区的指针.

我试图使用异常而不是返回错误代码.我还希望在需要它们的地方创建缓冲区,并在不再需要它们之后立即释放它们.

然而,看起来很难看的是,如果出现错误,无论我是否返回错误代码或抛出异常,我仍然应该记得清理到那时为止创建的任何缓冲区.如果我有10个缓冲区和10个可能的错误点,我将不得不调用free()100次(在每个错误情况下记得释放每个缓冲区).

现在假设我或者更糟糕的是,我的同事想要改变一些逻辑,比如在中间的某个地方添加另一个缓冲区.现在,他必须通过方法的其余部分查看可能发生的所有错误,并在每个这样的位置为该缓冲区添加free().如果他赶时间,他可以很容易地忽略一些这样的地方,并且你有内存泄漏.

这也极大地淹没了代码.

finally关键字可以解决Java或C#中的问题.无论代码在哪里发生异常,我仍然会在"finally"中清理所有缓冲区(顺便说一句,你不需要使用垃圾收集).在我理解的C++中,我可能必须为任何这样的缓冲区创建一个成员变量,并在析构函数中确保清理缓冲区.看起来对我来说也很难看,因为名为"pBuffer"的成员变量,即使是私有变量,也只是垃圾,因为它只在一个方法中使用(在本例中是构造函数),并且其余部分始终为NULL.时间.

必须是一个常见问题,但我没有设法使用搜索找到答案.谢谢!

Stu*_*etz 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