The code below works fine when compiling C ++, but causes (for example) access violation (System.AccessViolationException) when compiling as C ++ / CLI ( /clr). In both cases, the code is compiled and linked without errors or warnings ( /W4).
c->g(std::move(p)); (excerpt)
It seems that the problem is that the temporary unique_ptr is created when the argument is destroyed before the function is called. This occurs when invoking virtual functions ( C::gand C::k), but does not occur when invoking non-virtual functions ( C::hand ::g). It happens whether the calling code is part of an unmanaged class ( struct) or managed ( ref struct). This will not happen if I complete the class #pragma unmanaged. (Sample code is compiled as unmanaged C ++ only when only C ++ / CLI functions are not used).
To some extent related: Linker error when using unique_ptr in C ++ / CLI , but my code codes are excellent.
Question (s): Is this a bug in the compiler? If so, is this a known bug? If not, is this a known C ++ / CLI limitation? Or else, an error in the code? If this is an error or a compiler restriction, is there a way (preferably a simple) workaround without changing the function signature (as suggested in this answer )?
(Generated code: although I am familiar with assembler, I did not understand disassembling the compiled C ++ / CLI process shown by the debugger where there is a call to the virtual function. When debugging ends, entering all the unique_ptr properties, but not the function call. ..)
(Some background: calling code, managed classes, is intended as a bridge between C # code and unmanaged C ++ libraries.)
:
Microsoft Visual Studio Professional 2015 14.0.25425.01 3,
Visual Studio 2015 (v140)
Microsoft.NET Framework 4.6.01038
:
14.0.24720.00 1
#include <memory>
#include <iostream>
using namespace std;
struct A
{
virtual ~A() { cout << "~A()" << endl; }
};
struct I
{
virtual void g(std::unique_ptr<A> p) = 0;
};
struct C : public I
{
virtual void g(std::unique_ptr<A> p) override { cout << "C::g()" << endl; }
void h(std::unique_ptr<A> p) { cout << "C::h()" << endl; }
virtual void k(std::unique_ptr<A> p) { cout << "C::k()" << endl; }
};
void g(std::unique_ptr<A> p) { cout << "g()" << endl; }
struct B
{
void bug(I * c) {
std::unique_ptr<A> p(new A);
c->g(std::move(p));
}
void bug2(C * c) {
std::unique_ptr<A> p(new A);
c->k(std::move(p));
}
void ok() {
std::unique_ptr<A> p(new A);
g(std::move(p));
}
void ok(C * c) {
std::unique_ptr<A> p(new A);
c->h(std::move(p));
}
};
int main()
{
auto b = new B;
b->ok();
C c;
b->ok(&c);
b->bug(&c);
b->bug2(&c);
return 0;
}
: A (?) MS Visual Studio 2013 Update 1 (?).