【问题标题】:Is gcroot necessary inside a native C++ function?在本机 C++ 函数中是否需要 gcroot?
【发布时间】:2018-05-18 10:21:59
【问题描述】:

我是 C++/cli 编程的新手,今天我在我的一个项目中遇到了gcroot,并且对它的用法感到困惑。 我发现gcrootGChandle 的包装器,它通知垃圾收集器正在引用托管对象,因此该对象不会被删除。

因此使用gcroot 在本机类中声明属性以保存对托管对象的引用是有意义的。但我发现gcroot 在项目中也随处使用,如下所示:

int NativeFunction()
{
    gcroot<ManagedType^> xx = gcnew ManagedType();
    return xx->FunctionCalled();
}

这种实现是一个好习惯吗?这里有必要使用gcroot吗?

如果我声明 xx 而不声明 gcroot 会怎样,例如:

ManagedType^ xx = gcnew ManagedType();

有什么问题吗?

【问题讨论】:

    标签: c++ visual-studio visual-c++ c++-cli clr


    【解决方案1】:

    这里有多个级别的错误。从大错特错开始,你是对的,使用gcroot&lt;&gt; 是完全没有必要的,而且是有害的。它是 GCHandle 的包装器,您将在运行时调用 GCHandle::Alloc()、GCHandle::ToIntPtr()、GCHandle::FromIntPtr() 和 GCHandle::Free()。没有任何好处,GC 已经可以在没有任何帮助的情况下找到 ManagedType 对象引用。即时编译器的主要职责。你的替代品很好。

    那么这到底是什么错误,无参数的 ManagedType 构造函数正在执行什么样的魔法?您必须看一下,这段代码的作者很可能没有意识到 static 关键字应该有用。所以他可以简单地编写 ManagedType::FunctionCalled() 并避免完全分配对象。过度依赖 gcroot 拐杖肯定会阻止他看到这一点。

    然后就是调用这个“本机代码”这个讨厌的问题。不是,它必须使用有效管理的 /clr 或 #pragma 进行编译。这会产生必须在运行时即时编译的 MSIL。就像托管代码一样。但是,如果没有托管代码的好处,它就像本机代码一样无法验证。并且没有原生代码的好处,你不会得到额外的优化器的爱。当使用 /clr 编译整个库时,这往往会变得更加糟糕。不幸的是,设计师的工作做得太好了,以至于无法让人注意到这一点,您只会观察到性能的损失。

    正确的方法是按照本机代码始终执行此操作的方式执行此操作。带有函数指针。你可以通过 Marshal::GetFunctionPointerForDelegate() 得到你需要的那个。然而,正确编写更难,除非您需要解决性能问题,否则您可能不应该在工作代码中考虑这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-21
      • 1970-01-01
      相关资源
      最近更新 更多