2012-09-19 31 views
7

我目前正在將auto_ptr的實例轉換爲unique_ptr,但是我遇到了問題。它在代碼的C++部分很好用,但是當我在託管的C++/CLI層(該軟件同時使用C#和C++)中執行時,會出現鏈接錯誤。它編譯好,但在鏈接時斷開。 auto_ptr從來沒有任何問題。在C++/CLI中使用unique_ptr時的鏈接器錯誤

我目前正在使用Visual Studio 2010.有誰知道在C++/CLI中使用unique_ptr有任何問題嗎?

我試着在下面的一段代碼中總結我的問題,但請注意,下面的代碼實際上編譯和工作(我檢查指針的所有權被正確移動)。編譯時我沒有看到鏈接錯誤,但下面的代碼是純C++而不是C++/CLI。我只想有一個代碼如何構造的簡單例子,以便鏈接器錯誤更有意義。

#include "stdafx.h" 
#include <vector> 
#include <memory> 
#include <utility> 

using namespace std; 

namespace Test { 

template< class T > 
struct LinAlgPoint3 { 
    LinAlgPoint3() { x = y = z = 0; }; 

    union { 
    struct {T x,y,z;} ; 
    T data_[3]; 
    }; 
}; 

class ContainerClass 
{ 
public: 
    void setUniquePtr(
    unique_ptr< vector< LinAlgPoint3<float> > > newUniquePtr1 , 
    unique_ptr< vector< unsigned char > > newUniquePtr2) 
    { 
    m_uniquePtr1 = move(newUniquePtr1); 
    m_uniquePtr2 = move(newUniquePtr2); 
    } 

private: 
    unique_ptr< vector< LinAlgPoint3<float> > > m_uniquePtr1; 
    unique_ptr< vector< unsigned char > > m_uniquePtr2; 
}; 

int main(int argc, char** argv) 
{ 
    auto pos = unique_ptr< vector< LinAlgPoint3<float> > >(new vector< LinAlgPoint3<float> >()); 
    auto name = unique_ptr< vector< unsigned char > >(new vector< unsigned char >()); 
    ContainerClass container; 
    container.setUniquePtr(move(pos), move(name)); 
} 

} //namespace Test 

鏈接時,我得到的錯誤是:

error LNK2028: unresolved token (0A0018A5) "private: __cdecl std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > const &)" ([email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *,class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *)" (?<MarshalCopy>@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@Z) 
1>TestClass.obj : error LNK2028: unresolved token (0A0018A6) "private: __cdecl std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > const &)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *,class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *)" (?<MarshalCopy>@[email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@Z) 
1>TestClass.obj : error LNK2019: unresolved external symbol "private: __cdecl std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > const &)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *,class std::unique_ptr<class std::vector<unsigned char,class std::allocator<unsigned char> >,struct std::default_delete<class std::vector<unsigned char,class std::allocator<unsigned char> > > > *)" (?<MarshalCopy>@[email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@Z) 
1>TestClass.obj : error LNK2019: unresolved external symbol "private: __cdecl std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > const &)" ([email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@@Z) referenced in function "public: static void __clrcall std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > >::<MarshalCopy>(class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *,class std::unique_ptr<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > >,struct std::default_delete<class std::vector<struct LinAlgPoint3<float>,class std::allocator<struct LinAlgPoint3<float> > > > > *)" (?<MarshalCopy>@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected]@Z) 
1>D:\Test\Test.dll : fatal error LNK1120: 4 unresolved externals 

正如你可以看到(如果你可以通過令人難以置信的可怕的消息得到)也有到MarshalCopy一些參考,這是令我擔心C++/CLI可能還不支持unique_ptr。

軟件的佈局

C# executable -> C++/CLI translation layer (dll) -> C++ dll 

所以C++的dll使用的unique_ptr編譯罰款,但C++/CLI DLL無法正常鏈接。

我忘記提及一些相當重要的事情:如果我使用unique_ptr更簡單的數據類型,例如一個字符串,它會成功鏈接。例如:

auto string1= unique_ptr<string>(new string(20000, 'S')); 
    auto string2 = unique_ptr<string>(new string(20000, 'A')); 
    string1= std::move(string2); 

,我也試着確保使用的變量,這樣編譯器不會優化它拿走。

編輯:我剛剛測試並稱接受unique_ptr<string>另一個外部功能,我試圖在上面string1發送和打破的!所以這個問題必須在生成的DLL之間,因爲std :: move()在每個文件/類中運行良好。

+0

當我們只看到錯誤而不是創建它們的代碼時,很難診斷問題。你說這個C++代碼有效,但你的實際C++/CLI代碼不能。你能寫一些C++/CLI代碼來展示這個問題嗎? –

+0

我可以嘗試...在我的日子裏沒有從頭開始編寫太多的C++/CLI :) – AzP

+0

註釋掉所有移動調用以獲得乾淨的編譯。移動語義是由C++編譯器實現的C++ 11功能。不是由C++/CLI編譯器。您可以發佈到connect.microsoft.com以搖動該樹。 –

回答

8

嗯,不知道它現在有多相關,但是我和C++/CLI有完全相同的問題,並用r值引用代替值來解決它。我的意思是: 無效setUniquePtr(的unique_ptr & &一個,的unique_ptr & & B)

這樣,它編譯但它不是做事情最徹底的方法。

+0

這應該被標記爲答案。爲我工作。 – AarCee

2

通讀這個複雜的錯誤信息,我認爲這是抱怨LinAlgPoint3結構沒有複製構造函數。嘗試實施複製構造函數,也許運營商===,看看是否修復它。

+0

謝謝你的好建議。你是對的,該類缺少賦值運算符以及複製構造函數(它已經有== ==),但是添加它們並沒有解決問題。:( – AzP

+0

我剛剛添加了一些更多的信息 – AzP

1

您不能在DLL之間傳遞C++對象,並期望它正常工作。

不同模塊的內存佈局可能不同。幾乎可以肯定地使用不同的分配器(這可以降低任何擁有內存的C++類型,包括string,vectorunique_ptr)。

使用指向純虛擬基類的指針可以幫助解決這個問題。或者,如果您有C++部分的源代碼,請嘗試將C++和C++/CLI鏈接到一個DLL中,而不是在單獨的DLL中引用C++代碼。

+0

但unique_ptr需要一個隱含的指向析構函數的指針,以便能夠根據類型調用正確的指針。 – AzP

+0

@AzP:它不僅僅是一個指向析構函數的指針,它專用於每個deleter。導致模塊邊界出現問題 –