非同步操作時的內存管理?

請教大家一個問題:

比如說我有一個A類,其中A類的post方法是一個非同步的操作

class A
{
public:
template &
void post(Handler handle) {
// async...
}
};

我要在foo的test中調用a對象的post方法,當post的業務處理完成後會通知xxx回調。

class foo
{
public:
void test() {
a.reset(new A());
a.post(xx);
}
void xx()
{
}
private:
boost::shared_ptr& a;
};

現在問題就來了,foo類的test函數也是頻繁調用的,也就是說post非同步函數還未執行完,又會產生一次test的調用,造成a對象被reset,這樣就錯誤。

後來,我又想不用智能指針,直接在test函數中進行這樣的設計

void test() {
A* a = new A();
a.post(XX);
}

但是這樣怎樣去進行內存管理呢?採用狀態機?

補充:post方法是一個非同步的,但是post方法裡面可能也會調用一些非同步的方法,總之最後會通知xx函數。


樓主的需求表達不太明確,你應該告訴知友你要解決的問題是什麼,而不是如何改你現在寫的代碼。

我只能按我從樓主的問題中讀到的,約定最終所有任務完成之後一定會調用`xx`函數,所以可以給`xx`做文章:

void test() {
A* a = new A();
a-&>post([=] () {
try {
XX(); // Call XX callback
} catch (...) {
// Do nothing...
}
delete a;
});
}

不知道樓主所要求的`xx`函數參數列表有什麼要求,我這裡假設的是空。

另外,我也假設是在`xx`函數被調用之後,不會再調用同一個A的成員函數。


正確的方法是這樣子的:

auto b = this-&>a;

a-&>post([b]()

{

// 你的代碼,譬如說調用xx

});

確保了post的回調結束之前,b都還在,不管你a怎麼reset都沒關係。


你需要boost::enable_shared_from_this和boost::bind,讓A類自己管理自己就好了

我就假設你用的asio吧,因為不清楚該怎麼修改你的代碼好,asio的example裡面就有很好的示例:Daytime.3 - An asynchronous TCP daytime server

簡單來說就是通過bind生成一個閉包來持有tcp_connection這個類的智能指針,這樣智能指針的引用計數就一直不會減少到0,也就不會釋放這個對象。在tcp_connection類內部就用shared_from_this()來獲取指針。只要還繼續發起非同步操作,就是中會有一個閉包持有這個智能指針,直到不在繼續發起非同步操作,就可以讓這個connection類自生自滅了。


可以在構造函數里new析構函數里delete,這代表每個foo對應一個A

可以用vector或list之類的把所有new出來的A保存起來,合適的時候delete,這代表一個foo對應多個A

可以在每次new之前先delete之前的A,這代表每個foo對應一個不定的A

由需求決定


這個不是很簡單嗎?改一下post()的回調函數,讓它回傳A的實例,把void xx()改成void xx(A* a),把a回傳給xx()去析構,根本用不著智能指針呀。如果不能改post(),可以用functor包裝一下。


手機答題。

以你的第二個方案為基礎。xx方法增加一個A *參數。回調xx時把a的指針傳回來,在xx方法中delete。

這個方法可行,不過感覺不是很優雅。

--Update-------------------------------

剛剛測試了一下,C++成員函數內部可以用delete this完成析構,釋放對象佔用的內存(查看彙編證實)。題主可以試著利用這一點。

BTW:看彙編時發現delete this對應的指令裡面有對this是否為NULL的檢查。請問 @vczh 這是C++標準還是g++ (Debian 4.4.5-8) 4.4.5的特性?


我一般用shared_ptr處理


推薦閱讀:

是否有可能發現一段內存被野指針修改了?
如何設計內存池?
為什麼調用 std::map::clear() 後內存佔用率沒有降低?
最近電腦每次開機內存佔用與上次關機時差不多,只有重啟後內存才會降到20左右,這是怎麼回事啊?
電腦內存突然佔用過多是為什麼?

TAG:C編程語言 | 內存管理 | C | 智能指針 | 狀態機 |