c++11 std::function的bug

c++11的std::function是一大亮點,具體優點我就不一一細說了,今天我來說一些使用std::function帶來的常見問題及處理。

std::function<bool(int,int)> compare = [](int a, int b){
    return a > b;
};

compare(1, 2);

以上是正常的基本使用。

但如果std::fucntion是類成員的時候,有時候在就會莫名其妙的crash了。
如下:

class Test
{
public:
    std::function<void()> delegate;
    void testDelegate()
    {
        if (delegate) {
            delegate();
        }
    }
};

void main()
{
    Test t;
    t.delegate = [](){
        printf("t.delegate\n");
    };
    t.testDelegate();

    Test * m = new Test;
    string s = "hello world!";
    m->delegate = [m, s](){
        delete m;
        printf("m->delegate\n%s\n", s.c_str());
    };
    m->testDelegate();
}

第一個測試是正常的使用,第二個測試就可能會crash了。爲什麼呢,因爲m已經被釋放了,成員delegate也被析構了。

執行delete m後,函數實體已經消亡,包括[]中catch的所有變量都也析構了,如變量s。所以再操作相關對象時就會crash,如果沒有crash那隻能說你運氣好。

也許你會問誰這麼笨直接寫delete在裏面,反正我是遇到了,不管是不是直接delete的。

解決方法也很簡單,但有點煩索。

class Test
{
public:
    std::fucntion<void()> delegate;
    void testDelegate()
    {
        if (delegate) {
            auto copy = delegate; // 複製函數實例,copy將不受Test對象的析構影響
            copy();
        }
    }
};

解決!

第二個問題,是std::function和初始化列表std::initializer_list結合使用引起的。

struct Test
{
    int m;
    string str;
    std::function<void()> callback;
};

void main()
{
    Test t1 = {0, "", [](){}};
    Test t2 = {0, "", nullptr};
    Test t3 = {0, ""};
    Test t4 = {0};
}

這時候t3和t4的callback,可能不會正常初始化爲nullptr。現象是隨機crash,猜測可能是篡改了其它的內存。

t1和t2不知道會不會正常,現在如果struct裏面有function,我會以次賦值,不再使用initializer_list,所以不是很清楚,有興趣的同學可以自己嘗試。

解決方法,就是隻能避免這種用法。

~~~~~~~~~~~~~~~~~~~
以上是我的個人遇到的問題及解決,僅供參考,不喜勿噴!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章