lua中兩個(以上)dll使用不同的lua靜態庫導致垃圾回收時程序崩潰

在這裏插入圖片描述
仔細看了崩潰的代碼以後,發現了一點蛛絲馬跡:
在luaopen_testlua函數裏的的調用如下:
lua_newtable----->lua_createtable---->luaH_new,在這個函數裏可以看到這些:

Table *luaH_new (lua_State *L, int narray, int nhash)
{
Table *t = luaM_new(L, Table);

    luaC_link(L, obj2gco(t), LUA_TTABLE);
    t->metatable = NULL;
    t->flags = cast_byte(~0);
    /* temporary values (kept only if some malloc fails) */
    t->array = NULL;
    t->sizearray = 0;
    t->lsizenode = 0;
    t->node = cast(Node *, dummynode);   // 注意這裏
    setarrayvector(L, t, narray);
    setnodevector(L, t, nhash);
    return t;

}

注意t->node = cast(Node *, dummynode);這一行。
這一行把t->node設置成lua內的一個空表dummynode,這個值是這樣定義的。
#define dummynode (&dummynode_)

static const Node dummynode_ = {
{{NULL}, LUA_TNIL}, /* value /
{{{NULL}, LUA_TNIL, NULL}} /
key */
};

也就是說這個玩意其實是一個static變量,這也就是杯具的原因,因爲我的dll和exe裏各有一份lua源碼,所以在我的進程空間也就存在兩個dummynode。

這個dummynode是在dll離申請的。。。但是釋放的時候是在exe裏釋放的。所以下面這段代碼:

void luaH_free (lua_State *L, Table *t) {
if (t->node != dummynode)
{
luaM_freearray(L, t->node, sizenode(t), Node);
}

    luaM_freearray(L, t->array, t->sizearray, TValue);
    luaM_free(L, t);

}

上面的if判斷就成功了 (t->node指向dll裏的 dummynode,而這裏的dummynode是exe裏的)

所以這個函數就在傻乎乎的釋放dll裏的dummynode,然後vs的crt在釋放的時候又去檢查了這個指針,然後就崩潰了。。。

          對於這種事情我覺得怎麼說呢?也許lua作者沒有考慮一個進程內有兩個lua模塊?也許他考慮了,但是沒法避免。這個也讓我理解了使用lib和使用dll的區別。這裏的解決辦法是把lua編譯成dll,然後所有模塊都引用這個dll。

一般情況下不會遇到這個崩潰,長時間運行時會觸發垃圾回收,因此上面的問題便顯現出來了,這個問題還真不好排查啊。

Lua的使用關係前後變化如圖:

在這裏插入圖片描述
解決方式:使用同一份lua源碼生成的lib來生成dll可以解決

參考:https://www.douban.com/note/98782461/
參考:https://www.it610.com/article/4783121.htm

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