我正试图在Windows 10上从C#调用一个最小的C函数。我使用mingw / g ++将C代码编译成.dll
事实证明,我必须使用Visual Studio定义opterator new[]
或编译.dll。否则我的C#程序崩溃时出现以下错误:
The program '[14740] Test.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
我真的很想了解这里究竟发生了什么,以及如何在不覆盖所有新/删除操作符但仍使用mingw的情况下解决此问题。
以下是重现错误的最小示例,包括解决方法(如果定义AddNewOperator
将定义operator new[]
并且生成的.dll将正常工作):
Test.cs(使用Visual Studio 2017编译/运行):
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("libTest", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
public static extern int TestFunction();
static void Main(string[] args)
{
Console.WriteLine("!!" + TestFunction());
}
}
用mingw编译的Test.cpp(见下文):
#include <new>
#include <cstdlib>
#ifdef AddNewOperator // This will fix the issue
void* operator new[](std::size_t sz){
return std::malloc(sz);
}
#end
extern "C" {
int __stdcall __declspec(dllexport) TestFunction() {
int* test = new int[3]; // removing this line will make everything work when building
return test[2];
}
这是构建脚本:
# Remove the following # and the compiled dll will work just fine
g++ -g -s -Wall -c -fmessage-length=0 Test.cpp #-DAddNewOperator
g++ -g -shared -o libTest.dll *.o -Wl,--subsystem,windows
编辑:编译x86而不是64位的所有内容也解决了问题(这对我来说再也没有选择)
答案 0 :(得分:1)
TL; DR
您遇到的问题非常棘手,实际上您的程序每次都会崩溃,无论是否有void* operator new[](size_t){...}
定义。
如果您调试程序,它实际上应该在删除test
变量时崩溃。此变量是使用mingw的新运算符创建的,但使用MSVC删除运算符删除,并且它们不是interoperable。所以你必须使用mingw的delete
函数。
你可以做一个简单的测试:
c ++代码:
int* test = nullptr;
int __stdcall __declspec(dllexport) TestFunction() {
test = new int[3]; // note test is global
return test[2];
}
void __stdcall _declspec(dllexport) CleanUp() {
delete[] test;
}
c#code:
public static extern int TestFunction();
public static extern int CleanUp();
static void Main(string[] args)
{
Console.WriteLine("!!" + TestFunction());
CleanUp();
}
我实际上并不确定,但我认为,mingw的malloc实现使用legacy C runtime使用HeapAlloc进行分配,使用HeapFree删除test
变量。简而言之,当您自定义operator new
并在{... 1}内部使用malloc
时,您只是幸运/不幸,它不会崩溃...
但是,如果使用Visual Studio编译它,则(dll和exe)都使用相同的运行时,因此分配/取消分配在同一个内存空间管理器中完成。 但是仍然是UB,你会遇到问题!例如:如果您使用msvc10创建库并希望将此库与msvc14一起使用,则可以在此处执行相同的操作!我记得一些问题,代码来自一个内存也被管理错误的bug;我们使用了用msvc11创建的库,但我们的代码是用msvc12编译的......