在C++/CLI中使用unique_ptr时发生链接器错误

Linker error when using unique_ptr in C++/CLI

本文关键字:ptr 链接 错误 unique C++ CLI      更新时间:2023-10-16

我目前正在将auto_ptr的实例转换为unique_ptr,但遇到了一个问题。它在代码的C++部分工作得很好,但在我的托管C++/CLI层(软件同时使用C#和C++)中执行时,我会出现链接错误。它编译得很好,但在链接时会中断。auto_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 &)" (??0?$unique_ptr@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@U?$default_delete@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@@2@@std@@$$FAEAA@AEBV01@@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>@?$unique_ptr@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@U?$default_delete@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@@2@@std@@$$FSMXPEAV12@0@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 &)" (??0?$unique_ptr@V?$vector@EV?$allocator@E@std@@@std@@U?$default_delete@V?$vector@EV?$allocator@E@std@@@std@@@2@@std@@$$FAEAA@AEBV01@@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>@?$unique_ptr@V?$vector@EV?$allocator@E@std@@@std@@U?$default_delete@V?$vector@EV?$allocator@E@std@@@std@@@2@@std@@$$FSMXPEAV12@0@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 &)" (??0?$unique_ptr@V?$vector@EV?$allocator@E@std@@@std@@U?$default_delete@V?$vector@EV?$allocator@E@std@@@std@@@2@@std@@$$FAEAA@AEBV01@@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>@?$unique_ptr@V?$vector@EV?$allocator@E@std@@@std@@U?$default_delete@V?$vector@EV?$allocator@E@std@@@std@@@2@@std@@$$FSMXPEAV12@0@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 &)" (??0?$unique_ptr@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@U?$default_delete@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@@2@@std@@$$FAEAA@AEBV01@@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>@?$unique_ptr@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@U?$default_delete@V?$vector@U?$LinAlgPoint3@M@Test@@V?$allocator@U?$LinAlgPoint3@M@Test@@@std@@@std@@@2@@std@@$$FSMXPEAV12@0@Z)
1>D:TestTest.dll : fatal error LNK1120: 4 unresolved externals

正如您所看到的(如果您能理解这些令人难以置信的可怕消息),有一些对MarshalCopy的引用,这让我担心C++/CLI可能还不支持unique_ptr。

软件的布局是

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

因此,使用unique_ptr可以很好地编译C++dll,但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()在每个文件/类中都能很好地工作。

好吧,我不知道它现在有多重要,但我在C++/CLI中遇到了完全相同的问题,并通过使用r值引用而不是值来解决它。我的意思是:void setUniquePtr(unique_ptr&a,unique_ptr&b)

这种编译方式虽然不是最干净的方式。

阅读那个复杂的错误消息,我认为这是在抱怨LinAlgPoint3结构没有复制构造函数。尝试实现复制构造函数,也许还有运算符===,看看这是否能修复它

您不能在DLL之间传递C++对象并期望它正常工作。

不同模块的内存布局可能不同。几乎可以肯定会使用不同的分配器(这会减少任何拥有内存的C++类型,包括stringvectorunique_ptr)。

使用指向纯虚拟基类的指针可以帮助实现这一点。

或者,如果您有C++部分的源代码,请尝试将C++和C++/CLI链接到单个DLL中,而不是在单独的DLL中引用C++代码。