【问题标题】:Crash on returning a System::String that was marshalled from a native C++ call返回从本机 C++ 调用编组的 System::String 时崩溃
【发布时间】:2017-11-20 23:36:47
【问题描述】:

我有一个本地 C++ dll,我从托管 c++ dll 调用它,而托管 c++ dll 从 C# 应用程序调用。

本机 dll 中的函数如下所示:

std::string NativeClass::Test()
{
    return std::string("some string");
}

调用它的托管 C++ 函数看起来像这样

String ^ ManagedClass::Test()
{
    std::string temp = this->_native->Test();
    String^ sRet = msclr::interop::marshal_as<String^>(temp);

    return sRet; // crashes here !!!
}

但是,在执行 return 语句时,应用程序崩溃并出现类似的错误

Debug Assertion Failed!
debug_heap.cpp
Line 980
Expression: __acrt_first_block == header

我查看了整个 Stackoverflow,但我还没有解决它。有什么想法吗?

【问题讨论】:

  • 如果您尝试在 return 语句之前使用任何一个字符串会发生什么?您能否添加非托管字符串的 printf 和托管字符串的 Debug.WriteLine,让我们知道会发生什么?
  • 非托管字符串写出“some string”,托管字符串写出“some string”
  • 标准 C++ 库类型(如 std::string)在被分配到一个 DLL 并在另一个 DLL 中销毁时,通常会表现得很糟糕。使用完全相同版本的 CRT 创建和销毁对象至关重要。请务必使用完全相同的设置(减去 /clr)使用完全相同的编译器版本重建该原生 DLL,需要 /MD。
  • @Tim49 尝试通过String^ sRet = gcnew String(temp.c_str()); 封送std::string。这是MSDN 建议的另一种方法。
  • 不要专注于编组,那不是失败的原因。爆炸的是 std::string 析构函数。 temp 对象在其作用域块的末尾被销毁,使它看起来像是失败的 return 语句。

标签: c++ c++-cli marshalling


【解决方案1】:

Hans 帮助解决了这个问题。确实是本机 dll 和托管 dll 中的 CRT 版本不匹配。我确定我已经检查过了,但显然错过了。否则代码按原样工作。谢谢。

【讨论】:

    猜你喜欢
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 2015-06-20
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多