本机dll中的动态内存分配

时间:2018-04-11 11:34:45

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

我有一个用C ++编写的本机(非托管).dll,它将从托管进程(C#程序)调用。在调试dll时,我遇到的问题是,当我使用new关键字在dll中创建对象时,我遇到了系统访问冲突异常。这仅在从托管进程调用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(至少在此项目中)分配内存时才会发生这种情况,我很遗憾需要使用它。我的问题是:有谁知道为什么这会导致异常以及如何避免它?

1 个答案:

答案 0 :(得分: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。但它是什么类型的例外?读或写?在什么类型的地址?代码或数据?