首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C/C++ 結合 Lua 實現智能指針與內存洩漏檢測機制

     編輯:C++ 入門

設計思路

利用 Lua 的垃圾回收器(GC)與弱表特性,輔助 C++ 實現引用計數智能指針,並在運行期監控對象生命週期,自動報告未釋放內存。

核心組件

  1. C++ 端:RefCounted 基類(虛構造、addRef/release)、IntrusivePtr<T> 智能指針模板。
  2. Lua 端:
    - registry["__cpp_objects"] = 弱鍵表 { [cpp_ptr] = true }
    - __gc 元方法:檢測 C++ 對象引用計數是否為 0,否則報警
  3. 綁定層:sol2 或手寫 lua_pushlightuserdata + luaL_ref 管理映射。

關鍵代碼框架

C++ 智能指針


class RefCounted {
    atomic ref_{1};
public:
    virtual ~RefCounted() = default;
    void addRef() { ref_.fetch_add(1, memory_order_relaxed); }
    void release() { if (ref_.fetch_sub(1, memory_order_acq_rel) == 1) delete this; }
    int refCount() const { return ref_.load(memory_order_relaxed); }
};

template
class IntrusivePtr {
    T* ptr_;
public:
    IntrusivePtr(T* p = nullptr) : ptr_(p) { if (ptr_) ptr_->addRef(); }
    ~IntrusivePtr() { if (ptr_) ptr_->release(); }
    IntrusivePtr(const IntrusivePtr& o) : ptr_(o.ptr_) { if (ptr_) ptr_->addRef(); }
    IntrusivePtr& operator=(const IntrusivePtr& o) {
        if (ptr_ != o.ptr_) { if (ptr_) ptr_->release(); ptr_ = o.ptr_; if (ptr_) ptr_->addRef(); }
        return *this;
    }
    T* get() const { return ptr_; }
    T& operator*() const { return *ptr_; }
    T* operator->() const { return ptr_; }
    explicit operator bool() const { return ptr_; }
};

Lua 綁定與弱表註冊


// 在 luaopen 時創建弱表
lua_newtable(L); // 表
lua_newtable(L); // 元表
lua_pushstring(L, "__mode"); lua_pushstring(L, "k"); lua_settable(L, -3); // 弱鍵
lua_setmetatable(L, -2);
lua_setfield(L, LUA_REGISTRYINDEX, "__cpp_objects"); // registry.__cpp_objects = weakTable

// 導出 C++ 對象到 Lua
void pushCppObject(lua_State* L, RefCounted* obj) {
    lua_pushlightuserdata(L, obj); // 鍵
    lua_pushboolean(L, 1);         // 值
    lua_settable(L, -3);           // weakTable[obj] = true
    // 設置 userdata 封裝(可選)
}

// Lua __gc 元方法(註冊到 userdata 元表)
int cppObjectGC(lua_State* L) {
    RefCounted* obj = (RefCounted*)lua_touserdata(L, 1);
    if (obj && obj->refCount() > 1) { // 仍有 C++ 端持有
        cerr << "[LEAK DETECTED] Object " << obj << " refCount=" << obj->refCount() << " at Lua GC\n";
        // 可選:強制釋放或記錄堆棧
    }
    return 0;
}

運行期洩漏檢測流程

  1. 程序啟動:初始化 Lua 狀態,註冊弱表、__gc 鉤子。
  2. 業務代碼:使用 IntrusivePtr 管理對象,跨 C++/Lua 傳遞時同步註冊/註銷弱表條目。
  3. Lua GC 觸發(定時/內存壓力/手動 collectgarbage()):遍歷弱表,檢查對象引用計數。
    - 計數 == 1(僅 Lua 引用):正常回收,從弱表移除。
    - 計數 > 1:C++ 端仍持有,可能為洩漏(邏輯錯誤未釋放),報警記錄。
  4. 程序退出前:強制 collectgarbage("count"),檢查弱表殘留,生成洩漏報告。

優勢與局限

優勢局限
零侵入業務邏輯,僅需換智能指針需嵌入 Lua 運行時(~200KB)
利用成熟 GC 機制,無需手寫掃描器弱表鍵為 lightuserdata,無法區分對象類型
支持熱加載腳本動態調整檢測策略多線程需同步 Lua 狀態訪問
可輸出 Lua 堆棧輔助定位洩漏源頭循環引用需 C++ 端自行斷開(weak_ptr 輔助)

總結

C++ 與 Lua 結合實現內存洩漏檢測,是「腳本語言托管資源生命週期」思想的創新應用。適合嵌入式腳本化引擎、遊戲邏輯層、插件系統等已集成 Lua 的項目,以極低成本獲得運行期洩漏防護能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved