Global 物件指的是如下的用法:
class Global_t
{
UTF8_String Hello{"Hello..."};
public:
// Destructor
~Global_t()
{
cout << "Global_t::~Global_t()" << endl;
}
UTF8_String cxxlFASTCALL GetHello() const
{
return Hello;
}
}g_Global;
特性有三:
- 程式或插件載入就會自動建好
- 任何可用到的使用端都能直接使用
- 程式或插件結束前會自動執行解構程序
問題就在其中有包含 UTF8_String,程式或插件結束時依機制並不直接執行其解構程序,而是交給 CxxlMan2 程式庫的垃圾處理機制。主程式還好,主程式結束後垃圾處理就不再運作。但若是插件,UTF8_String 要叫用解構程式時,插件已卸載了無法執行了。
解決的辦法有兩個方向,第一個不要在 Global 中有任何 cxxlObject 的成份;若非有不可就用以下建議的第二種方法,也許還有第三、第四...種方法也說不定
class Global_t;
Smart_Ptr<Global_t> cxxlFASTCALL Get_Global();
class Global_t:virtual public LifeObject<true>
{
UTF8_String Hello{"Hello..."};
// Constructor
Global_t()
{
cout << "Global_t Constructor" << endl;
}
public:
// Destructor
~Global_t()
{
cout << "Global_t Destructor" << endl;
}
UTF8_String cxxlFASTCALL GetHello() const
{
return Hello;
}
friend Smart_Ptr<Global_t> cxxlFASTCALL Get_Global();
};
// 取得 Global_t 物件,若 Global_t 物件還不存在會先產生
Smart_Ptr<Global_t> cxxlFASTCALL Get_Global()
{
static mutex mtx;
class Notify_LifeMonitor;
// Globar_t 物件定義在這,須由 Get_Global() 取得
static Smart_Ptr<Notify_LifeMonitor> m_Global_Ptr;
// 作為 LifeMonitor 的通知處理,務必讓 LifeMonitor 被放棄持有
// 這是為了讓 m_Notify_Global_Ptr 放棄持有 LifeMonitor 而量身訂作
class Notify_LifeMonitor :public LifeMonitor<Global_t>
{
public:
// Constructor
Notify_LifeMonitor(const Smart_Ptr<Global_t>& Obj)
:LifeMonitor<Global_t>(Obj)
{
}
// 通知須把 LifeMonitor 釋放
virtual void cxxlFASTCALL DoDelNotify() override
{
lock_guard<mutex> lck(mtx);
m_Global_Ptr.Destroy();
}
};
lock_guard<mutex> lck(mtx);
if (m_Global_Ptr.isNULL())
{
// 在執行時期要用時才產生 Global_t 物件
m_Global_Ptr = new Notify_LifeMonitor(new Global_t);
}
return m_Global_Ptr->GetLifeObject();
}
Global_t 不再做成 Global 物件,為了達到 Global_t 物件在插件結束前會自動執行解構程序,所以定義成 LifeObject<true>,才能在 dll 無使用時,Global_t 和 dll 可一起釋放,但 Global_t 會先釋放
範例下載:
沒有留言:
張貼留言