Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linker error when using unique_ptr in C++/CLI

I'm currently converting my instances of auto_ptr to unique_ptr, but I'm hitting an issue. It works great in the C++ part of the code, but when doing it in my managed C++/CLI layer (the software uses both C# and C++) I get link errors. It compiles fine, but it breaks at link time. There were never any issues with auto_ptr.

I'm currently using Visual Studio 2010. Does anybody know of any issues with using unique_ptr in C++/CLI?

I've tried to sum up my issue in a piece of code below, but please be aware that the code below actually compiles and works (I checked that the ownership of the pointers get moved properly). I'm not getting linking errors when compiling this, but the code below is pure C++ and not C++/CLI. I just wanted to have a minimal example of how the code is constructed so the linker error makes more sense to read.

#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

The error I get when linking is the following:

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:\Test\Test.dll : fatal error LNK1120: 4 unresolved externals

As you can see (if you can get through the incredibly horrible messages) there are some references to MarshalCopy, something that makes me worry that C++/CLI might not support unique_ptr yet.

The layout of the software is

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

So the C++ dll compiles fine using unique_ptr, but the C++/CLI dll is unable to link properly.

I forgot to mention something quite important: If I use unique_ptr to a simpler datatype, for instance a string, it links successfully. For example:

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

and I've also tried to make sure to use the variable so the compiler doesn't optimize it away.

Edit: I've just tested adding another external function that accepts a unique_ptr<string>, and I tried sending in the above string1 and that breaks as well! So the issue must be between the generated DLLs, since the std::move() works well within each file/class.

like image 583
AzP Avatar asked Sep 19 '12 10:09

AzP


People also ask

What is a std:: unique_ ptr?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

How to transfer ownership unique_ ptr?

In C++11 we can transfer the ownership of an object to another unique_ptr using std::move() . After the ownership transfer, the smart pointer that ceded the ownership becomes null and get() returns nullptr.

How does unique_ ptr work?

A unique_ptr object wraps around a raw pointer and its responsible for its lifetime. When this object is destructed then in its destructor it deletes the associated raw pointer. unique_ptr has its -> and * operator overloaded, so it can be used similar to normal pointer.


2 Answers

Well, don't know how relevant it is now, but I had exactly same problem with C++/CLI and solved it with taking r-value reference instead of value. I mean: void setUniquePtr(unique_ptr&& a, unique_ptr&& b)

This way it compiles though it's not a cleanest way to do things.

like image 110
zen-cat Avatar answered Nov 02 '22 21:11

zen-cat


Reading through that complex error message, I think it's complaining that the LinAlgPoint3 struct doesn't have a copy constructor. Try implementing the copy constructor, and maybe operators = and ==, and see if that fixes it.

like image 40
David Yaw Avatar answered Nov 02 '22 22:11

David Yaw