【问题标题】:Dynamic memory allocation in native dll本机 dll 中的动态内存分配
【发布时间】:2018-09-21 06:42:50
【问题描述】:

我有一个用 C++ 编写的本机(非托管).dll,它将从托管进程(C# 程序)中调用。在调试 dll 时,我发现的问题是,当我在 dll 中使用 new 关键字创建对象时,出现系统访问冲突异常。这仅在从托管进程调用 dll 时出现,而不是在我从另一个本机程序调用它时出现。

代码是这样的:

// Native.dll file
MyClass myInstance; // global variable (and does need to be so)
__declspec(dllexport) uint8_t _stdcall NativeFunction(){
    myInstance = new MyClass(); // <-- this causes Access Violation Exception
}

和 C# 代码:

using System.Runtime.Interopservices;
// Loading the dll
[DllImport("Native.dll",CallingConvention = CallingConvention.StdCall)]
private extern static byte NativeFunction();

class TestClass{
   byte returnVal = NativeFunction(); //<-- exception in managed context
}

我知道这与试图在允许的内存空间之外分配内存的本机进程有关。仅当使用new(至少在这个项目中)分配内存时才会发生这种情况,不幸的是我确实需要使用它。我的问题是:有谁知道为什么会导致异常以及如何避免它?

【问题讨论】:

    标签: c# c++ interop access-violation interopservices


    【解决方案1】:

    new MyClass 很可能会调用全局运算符::operator new,除非您提供了MyClass::operator new。如果你自己没有提供::operator new,你应该从你的编译器(可能是Visual Studio)获得::operator new

    这个::operator new 实现可能会转发到HeapAlloc。你猜怎么着?这与 .Net 也将调用的 Win32 函数相同。这里没有太多魔法。这就是 Windows 将内存页分配给您的虚拟地址空间的方式。当您使用这些页面时,Windows 会分配 RAM。

    现在这里的事情是你不需要为此做任何特别的事情。事实上,做任何特别的事情都会打破 operator new。既然你把它弄坏了,你就必须弄清楚这一点。这里没有太多神奇的代码。使用调试版本,因此您将有一个清晰的堆栈转储(无内联)。可以回溯到HeapAlloc吗?

    还要检查访问冲突异常的内容。错误代码将为 C0000005。但它是什么类型的异常?读还是写?在什么类型的地址上?代码还是数据?

    【讨论】:

    • 所以消息是Exception thrown at 0x001E15D9 in TheManagedCode.exe: 0xC0000005: Access violation reading location 0x00000004. 我不确定我是否完全关注你;如果我没有提供我自己的::operator new 那怎么破呢?
    • @skitiddu:好吧,既然你没有预先提供这些信息,我只介绍了几个案例。所以这里的问题是read。这显然是在取消引用一个空指针,但为什么呢?下一条信息是导致它的指令,位于0x001.....。这可能在EXE中。为什么会在里面?静态阴极射线管? operator new 通常位于 DLL 中(因为您希望它被所有模块共享)。
    猜你喜欢
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 2021-02-15
    • 2013-07-01
    相关资源
    最近更新 更多