C 11 function 實現委託機制為什麼會自動釋放委託的函式

時間 2021-06-01 18:42:39

1樓:

超級慘的車禍現場...

第零點auto i_process_task = std::bind(std::move(&Boss::

onProcess), std::move(*this), _1, _2);

這行過後,this 所指向的 i_boss 對應的物件會被移動到了 i_process_task 裡的某個變數裡,i_boss._work_list 只剩個空 vector,因此迴圈第一遍結束後回到

for (auto itor : _worker_list)

這裡迭代器已失效。VS Debug 配置下會被

_DEBUG_ERROR("vector iterator not incrementable");

搞掛掉。

解決方案是,把 std::move(*this) 換成 this。

第一點for (auto itor : _worker_list)

這麼寫等於建立了個臨時變數 itor,每次迴圈把 _worker_list 裡的物件複製到 itor。結果導致每次迴圈都把 i_process_task 和 i_result_task 賦值給了乙個臨時物件。第二次迴圈裡這個臨時變數裡的物件會被新的 worker2 物件替代,迴圈結束後這個物件及其的成員變數就析構了。

你新建的執行緒裡繼續訪問 lambda 繫結的這個臨時變數有可能訪問到的是 worker2 或者被析構後的無效空間。。解決方案是改成 auto &itor。

第二點worker1 裡新執行緒繫結的 this 指標指向的是迴圈建立的臨時變數 itor。第一遍迴圈結束後就沒舊物件的事兒了,第二遍迴圈在相同的位置建立 worker2,導致 worker1 建立的執行緒裡通過指標訪問到了新的 worker2 物件,看起來像是 worker1 改名了。

建議閱讀 c++ - Using std::bind with member function, use object pointer or not for this argument? 和 Effective Modern C++ Item 23。

最後,可以考慮給 Worker 和 Boss 都加上下面這幾個函式,然後執行或者單步,體會一下到底有多慘

Boss()

Boss(const Boss &o) :_worker_list(o._worker_list)

Boss(Boss &&o) :_worker_list(std::move(o._worker_list))

~Boss()

部分輸出:

# main

00D759BE Boos()

# hireWorker

008FFC78 Worker(string) tom report

008FFC00 Worker(string) leo report

00DC1A18 Worker(const Worker&)

00DC42E8 Worker(Worker&&)

00DC1A18 ~Worker()

00DC4358 Worker(const Worker&)

008FFC00 ~Worker()

008FFC78 ~Worker()

# loop

008FFC38 Worker(const Worker&)

-- 1 1 --

00D752B2 Boos(Boos&&)

-- 1 2 --

00DC43F8 Worker(const Worker&)

00DC4468 Worker(const Worker&)

00D75242 Boos(const Boos&)

00D74ABA Boos(Boos&&)

00D752AE ~Boos()

00DC4D10 Worker(const Worker&)

00DC4D80 Worker(const Worker&)

00D7488E Boos(const Boos&)

accept task

00D7498A ~Boos()

00DC43F8 ~Worker()

00DC4468 ~Worker()

-- 1 3 --

00D752B2 Boos(Boos&&)

-- 1 4 --

00D75242 Boos(const Boos&)

00D74ABA Boos(Boos&&)

00D752AE ~Boos()

00D7488E Boos(const Boos&)

00D7498A ~Boos()

-- 1 5 --

report to boss: 0

2樓:

我注意到有三個問題:

1. range for 遍歷_worker_list的時候沒有用引用, 導致臨時生成Worker

2. bind的時候第乙個引數給的是std::move(*this), 這個意味著i_process_task儲存的Boss例項不是main裡面那個,可以列印對應的this指標驗證

3. i_process_task和i_result_task分配在棧上, 所以離開作用域會被析構, 並引起析構生成的Boss例項, 可以在Boss的析構函式列印資訊驗證

換名的現象應該是1造成的, 因為i_thread裡面捕獲了worker的this指標來訪問_worker_name, 當第二次迴圈的時候, 臨時生成的Worker的位址和第一次一樣,所以都打出來的是第二個worker的名字

至於std::move(*this)那個地方, 我分析半天沒理清, 試著delete Boss的copy constructor等, gcc報的錯糊我一臉, 所以放棄了, 等大神分析吧

另外, 把std::move(*this)換成this, 能正確工作

C 如何實現優先佇列?

原生的Priority Queue已經被merge了 API 描述如下,感覺上符合大部分的需求了,應該是不是執行緒安全的,需要注意 namespace System.Collections.Generic public class PriorityQueue NB does not implemen...

c 裡如何實現static warning?

原子筆 template X struct example It just declares a function but does not define a variable define static warning x,str example x 0 1 30 str example 0 in...

能用c語言演算法實現嗎?

uciicu include int main int A,B,C,D,n 分為ABCD四個數,n僅為計算該程式最終迴圈次數,非必要 int a,b,c,d for A 1 A 7 A 按照題設,每個數最小為1最大為7 for B A B 7 B for C B C 7 C for D D D 7 ...