内存管理策略的问题

Problems with memory management strategy

本文关键字:问题 策略 管理 内存      更新时间:2023-10-16

在最新的C++编程语言书中,Bjarne提出了一种替代传统错误处理的方法,即使用异常。这在第13.3.1章中,他写道:

void test()
     // handle undiciplined resource acquisition
     // demonstrate that arbitrary actions are possible
{
     int* p = new int{7};                              // probably should use a unique_ptr (§5.2)
     int* buf = (int*)malloc(100*sizeof(int));         // C-style allocation
     auto act1 = finally([&]{   delete p;
                                free(buf);             // C-style deallocation
                                cout<< "Goodby, Cruel world!n";
                           }
                     );
     int var = 0;
     cout << "var = " << var << 'n';
     // nested block:
     {
           var = 1;
           auto act2 = finally([&]{ cout<< "finally!n"; var=7; });
           cout << "var = " << var << 'n';
     } // act2 is invoked here
     cout << "var = " << var << 'n';
}// act1 is invoked here

虽然我理解他试图解释的内容以及这个代码应该实现的目标,但我不相信这个片段是无韭菜的:

> 1.    int* p = new int{7};                              // probably should use a unique_ptr (§5.2)
>   2.           int* buf = (int*)malloc(100*sizeof(int));         // C-style allocation
>         
>     
> 3.         auto act1 = finally([&]{   delete p;
>                                         free(buf);             // C-style deallocation
>                                         cout<< "Goodby, Cruel world!n";
>                                    }
>                              );

为什么?因为如果在第二行(2)中,我们抛出了异常(假设没有对malloc的调用,而是对一个可以实际抛出的函数的调用,我相信Bjarne试图解释的概念是使用finally构造,而这里的malloc调用是不相关的,是偶然的,可以被任何调用所取代),那么如果两次抛出,那么3将永远无法到达,我们有来自1的资源韭菜。我说得对吗?

基本上,在上面的代码段中发生的是:

     int* p = new int{7};                              // probably should use a unique_ptr 
     int* buf = (int*)malloc(100*sizeof(int));         // C-style allocation

内存是通过C++newC malloc分配的。这两个指针都不受管理,如果此时抛出任何代码,那么内存就会泄漏。但是,请注意,malloc不会抛出,因此在隔离状态下,此代码是安全的。

http://en.cppreference.com/w/cpp/memory/c/malloc

    auto act1 = finally([&]{   delete p;
                            free(buf);             // C-style deallocation
                            cout<< "Goodby, Cruel world!n";
                       }
                 );

在这段代码中,一个RAII类型是从finally函数返回的。当act1被销毁时(在异常或离开此范围时),它将执行可调用参数。

因为这直接遵循malloc,所以我们现在已经确保了内存不会泄漏。

但是以下代码是不安全的:

      int* p = new int{7};                              // probably should use a unique_ptr 
     int* buf = (int*)malloc(100*sizeof(int));         // C-style allocation
     throwing_function();
     auto act1 = finally([&]{   delete p;
                            free(buf);             // C-style deallocation
                            cout<< "Goodby, Cruel world!n";
                       }
                 );

然而Bjarne的评论很到位,只需使用std::unique_ptr即可。

编辑:

最后使用:

database_handle dh1;
dh1.do("action...");
finally([&]{
    if(!dh1.success()) {
        dh1.rollback();
    }
);