我今天在XCode下這種奇怪的lambdas行爲已經非常困難 - 在試圖追蹤iOS中圍繞代碼的幾處內存泄漏之後,我縮小了它的範圍到這一點(類似)的片段(S),我使用的是共享指針的東西的所有權分配給延期任務:C++ lambda將不會調用析構函數在按值捕獲的成員上
void DBStorage::dispose(std::shared_ptr<DataChunk>& dc)
{
backgroundQueue.queueTask([=]() {
assert(dc.use_count() == 1);
if (dc->isDirty()) {
//store to disk
}
});
}
(請注意,共享指針的使用計數始終爲1,當拉姆達運行)
執行後,這個任務是空的 - 我想用pendingJob = nullptr;
來調用所有按值捕獲的析構函數對象,因此是DataChunk
的析構函數。 但是,它看起來像是在XCode/LLVM lc
的析構函數中永遠不會被調用;使用mutable
明確調用它的dtor,並用簡單的delete
刪除std::function
也不起作用。
這是標準行爲嗎? 我當然可以手動調用dc.reset()
,它按預期工作,但這相當重要的是使用共享指針模擬。
解決方案 顯然,這是一個known gcc bug。
的Contrib
單機與輸出採樣從Xcode中5.0.2 /鐺3.3
#include <iostream>
#include <memory>
void fnRef(std::shared_ptr<int>& ptr)
{
auto lambda = [=]() { std::cout << ptr.use_count() << ':' << __PRETTY_FUNCTION__ << '\n'; };
lambda();
}
void fnVal(std::shared_ptr<int> ptr)
{
auto lambda = [=]() { std::cout << ptr.use_count() << ':' << __PRETTY_FUNCTION__ << '\n'; };
lambda();
}
int main()
{
std::shared_ptr<int> ptr(new int);
for (int i=0; i<10; ++i)
fnVal(ptr);
std::cout << '\n';
for (int i=0; i<10; ++i)
fnRef(ptr);
return 0;
}
LLVM/GCC輸出
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
3:void fnVal(std::shared_ptr<int>)::<anonymous class>::operator()() const
2:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
3:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
4:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
5:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
6:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
7:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
8:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
9:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
10:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
11:void fnRef(std::shared_ptr<int> &)::<anonymous class>::operator()() const
IDEOne.com Output for same code
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
3:fnVal(std::shared_ptr<int>)::__lambda1
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
2:fnRef(std::shared_ptr<int>&)::__lambda0
的Visual Studio 2013的輸出
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
3:fnVal::<lambda_67137a3f93ee478c018cc7068004c9fd>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
2:fnRef::<lambda_70f241d4201227663d23c74be170d302>::operator()
您使用的是哪個版本的編譯器?海灣合作委員會存在一個錯誤,即一個參考值的捕獲是一個參考。 http://stackoverflow.com/questions/6529177/capturing-reference-variable-by-copy-in-c0x-lambda –
'clang --version'說,'Apple LLVM 5.0版(clang-500.2.75)(基於在LLVM 3上。3svn)' - 這絕對是可能的,但是首先在本地範圍內複製'dc'然後捕獲副本也不起作用! – Tom89
湯姆,你沒有看到我*只是*寫過一個示例代碼的相同問題,現在我無法重現它爲我的生活。當我說「正義」時,我的意思是5分鐘前。我改變了一個'std :: cout'的位置,現在不再發生了,並且改變了*返回*沒有關係。不,我沒有這樣做。我會看到我可以再次做到這一點。 (和我運行相同的Xcode /叮噹你,順便說一句)。 – WhozCraig