RAII 概念(Resource acquisition is initialization)

RAII 概念

RAII(Resource acquisition is initialization)中文即是"資源取得或分配即是在初始化".
看起來有點攏統. 個人的理解是RAII是用於object上的一個寫法.
物件建立的時候, 資源取得的是時候是經由constructor來初始. 結束的時候便透過destructor來釋放.
這樣的好處就是可以確保資源在物件的生命週期內是存在的.
結束的時候就會釋放掉資源. 閉免掉memory leak的問題或因為資源的關係導致程式運作不正常

C++程式範例

底下以[3]的程式作為範例, 如下所示. bad()會造成程式lock住. 而改為RAII的good()方式可以避免掉這問題.

std::mutex m;

void bad() 
{
    m.lock(); // 直接取的 lock
    f();  // (1) 當有例外發生(exception), 程式鎖死 
    if(!everything_ok()) 
 return;  // (2) 程式直接返回, 程式鎖死 
    m.unlock();  //  釋放lock
}

void good()
{
    // 使用class包住lock. 而這邊不需像上述使用unlock.
    // 因為object結束會呼叫解構子. 會做unlok
    std::lock_guard<std::mutex> lk(m); 
    f(); // (1) 當例外造成, lock object也會結束
    if(!everything_ok()) return; // (2) 程式返回,  lock object也會結束
}  // 正常結束, lock object也會結束

C結合RAII

因為之前寫C的時候, 每次都會為了malloc()跟free(), 讓程式碼不簡潔或造成編譯問題.
(1) 如程式有重複的release資源的code.
(2) 透過goto方式集中資源釋放, 但導致在goto之後的變數宣告無法初始數值

#include<stdio.h>
#include<stdlib.h>
#include<memory>
const int CB_MEM_SIEZ = 1000000;

int main()
{
    int *piData = (int *) malloc(sizeof(int) * 10);

    if(true)
    {
        free(piData);       ///< case 1. redundant codes
        return 0;
    }

    if(true)
        goto exit_main;

    // case 2. ERROR:
    // "jump bypasses variable initialization" or "crossed initialization"
    // use "int b; b = 0;" instead of "int b = 0;" to avoid error
    int b = 0;

exit_main:
    free(piData);
    return 0;
}

而C語言基本上是程序語言. 基本上靠自己是無法用到RAII的方式. 幸好C跟C++是通用.
這邊就嘗試使用C++的smart pointer來達成RAII的寫法
程式碼如下, 主要是參考[4][5][6][7]. 使用不同的方式實現RAII.
藉由這樣的方式來減少case 1&2的寫法.

#include<stdio.h>
#include<stdlib.h>
#include<memory>
const int CB_MEM_SIEZ = 1000000;

struct Deletor
{
    void operator()(int *piData)
    {
        printf("free by operator\n");
        free(piData);
    }
};

int main()
{

    // share ptr
    {
        /*
        // 1
        std::shared_ptr<int> sp( \
                (int*) malloc(sizeof(int) * CB_MEM_SIEZ), \
                [] (int *piData) { printf("share ptr free\n"); free(piData); } \
                );
        */

        // 2
        std::shared_ptr<int> sp( \
                (int*) malloc(sizeof(int) * CB_MEM_SIEZ), \
                Deletor() \
                );
    }

    // unique ptr
    {
        /*
        // 1-1
        std::unique_ptr<int, void (*)(int *)> up(\
                (int*) malloc(sizeof(int) * CB_MEM_SIEZ), \
                [] (int *piData) { printf("unique ptr free\n"); free(piData); }\
                );
        */
        /*
        // 1-2 "decltype(free)*" as "void (void*)"
        std::unique_ptr<int, decltype(free)*> up(\
                (int*) malloc(sizeof(int) * CB_MEM_SIEZ), \
                free \
                );
        */

        // 2
        std::unique_ptr<int, struct Deletor> up(\
                (int*) malloc(sizeof(int) * CB_MEM_SIEZ)
                );
    }
    return 0;
}

補充: Array 的方式

參閱[8]修改而來的code. 要注意一點"*","->"在smart pointer已被使用在member function or member variable上

#include<stdio.h>
#include<stdlib.h>
#include<memory>

int main()
{
    std::unique_ptr<int[]> arrup (new int[5]);
    arrup[0]=5;
    // printf("%d\n", *arrup); //error, operator * not defined
    printf("%d\n", arrup[0]);
    std::unique_ptr<char[], void (*)(void *)> charup ((char*)(malloc(5)), free);
    charup[1]='b';
    printf("%c\n", charup[1]);
    return 0;
}

Reference

  1. Wiki - RAII
  2. C++ RAII
  3. cppreference - raii
  4. Using std::unique_ptr (RAII) with malloc() and free()
  5. Is it possible to use a C++ smart pointers together with C's malloc?
  6. cplusplus - unique_ptr
  7. cplusplus - shared_ptr
  8. The Smart Pointer That Makes Your C++ Applications Safer - std::unique_ptr

留言

  1. I am very glad that you always put in so much effort. With my remote developers working with me earlier, the updated tech niches were impossible to address. So, I always refused to have those projects due to the lack of an operational team. One day, my ex-colleague, who is also running a game-developing business, suggested Eiliana.com, and I rushed to see the magic. I hired a few experts, and it transformed my business.

    回覆刪除

張貼留言

這個網誌中的熱門文章

yocto recipe : (1) 撰寫 recipe

yocto recipe : (2) 撰寫 bbappend

yocto recipe : (3) 使用 External Source 來編譯軟體