将 unique_ptr 传递给虚函数时的 C++/CLI 编译器错误?

Pab*_*o H 5 virtual-functions c++-cli unique-ptr visual-studio-2015

下面包含的代码在编译为 C++ 时工作正常,但在编译为 C++/CLI ( /clr)时会导致(例如)访问冲突 (System.AccessViolationException )。在这两种情况下,代码编译和链接都没有错误或警告 ( /W4)。

c->g(std::move(p)); (摘抄)

问题似乎是调用函数之前创建的临时 unique_ptr 参数被销毁。这在调用虚函数 ( C::gand C::k) 时发生,但在调用非虚函数 ( C::hand ::g)时不会发生。无论调用代码是非托管类 ( struct) 还是托管类 ( ) 的一部分,都会发生这种情况ref struct。它不是,如果我换用类发生#pragma unmanaged。(当然,示例代码仅在不使用 C++/CLI-only 功能时才编译为非托管 C++。)

有点相关:在 C++/CLI 中使用 unique_ptr 时出现链接器错误,但我的代码链接正常。

问题:这是编译器中的错误吗?如果是这样,这是一个已知的错误吗?如果不是,它是否是 C++/CLI 的已知限制?或者,代码中的错误?如果是编译器错误或限制,是否有(最好是简单的)解决方法而不更改函数签名(如本答案中所建议)?

(生成的代码:虽然我熟悉汇编,但我不明白,在调试器显示的C++/CLI编译过程的反汇编中,对虚函数的调用在哪里。调试时我最终只步入所有unique_ptr 的东西,但不是函数调用......)

(一些背景:调用代码、托管类旨在作为 C# 代码和非托管 C++ 库之间的桥梁。)

使用:
Microsoft Visual Studio Professional 2015 Version 14.0.25425.01 Update 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; }

//#pragma unmanaged
/*public ref*/ struct B
{
    void bug(I * c) {
        std::unique_ptr<A> p(new A);
        c->g(std::move(p)); // *p destroyed before reaching g() when /clr
    }
    void bug2(C * c) {
        std::unique_ptr<A> p(new A);
        c->k(std::move(p)); // *p destroyed before reaching g() when /clr
    }
    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));
    }
};
//#pragma managed

int main()
{
    auto b = /*gcnew*/ new B;
    b->ok();
    C c;
    b->ok(&c);
    b->bug(&c);
    b->bug2(&c);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

更新:针对 Visual Studio 2013 Update 1向 MS 报告了一个(非常?)类似问题,据称已解决(?)。

更新:Visual Studio Developer Community 上报告了这个或类似的问题。他们报告问题仍然存在于 VS2015.3 (C++ 19.00.24215.1) 和 VS2017.6 Preview 5 (C++ 19.13.26127.1) 中。