Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的mingw DLL:为什么我必须重写new/delete?_C#_C++_Windows_Dll_Mingw - Fatal编程技术网

C#中的mingw DLL:为什么我必须重写new/delete?

C#中的mingw DLL:为什么我必须重写new/delete?,c#,c++,windows,dll,mingw,C#,C++,Windows,Dll,Mingw,我试图从Windows10上的C#调用一个最小的C函数。我使用mingw/g++将C代码编译成.dll 事实证明,我必须定义opterator new[]或使用Visual Studio编译.dll。否则,我的C#程序将崩溃,并出现以下错误: 程序“[14740]Test.exe”已退出,代码为-1073741819(0xc0000005)“访问冲突”。 我真的很想了解这里到底发生了什么,以及如何在不覆盖所有新建/删除运算符但仍使用mingw的情况下解决此问题 下面是一个复制错误的最小示例,包括

我试图从Windows10上的C#调用一个最小的C函数。我使用mingw/g++将C代码编译成.dll

事实证明,我必须定义
opterator new[]
或使用Visual Studio编译.dll。否则,我的C#程序将崩溃,并出现以下错误:

程序“[14740]Test.exe”已退出,代码为-1073741819(0xc0000005)“访问冲突”。

我真的很想了解这里到底发生了什么,以及如何在不覆盖所有新建/删除运算符但仍使用mingw的情况下解决此问题

下面是一个复制错误的最小示例,包括一个解决方法(如果定义了
AddNewOperator
,则将定义
operator new[]
,并且生成的.dll将正常工作):

Test.cs(使用Visual Studio 2017编译/运行):

使用mingw编译的Test.cpp(见下文):

编辑:为x86而不是64位编译所有内容也解决了这个问题(我也没有选择)

TL;博士

您不能在编译器之间混合分配/取消分配! 您面临的问题相当棘手,实际上,无论是否使用
void*操作符new[](size\u t){…}
定义,您的程序每次都会崩溃

如果调试程序,它实际上应该在删除
test
变量时崩溃。此变量是使用mingw的新运算符创建的,但使用MSVC delete运算符删除,而不是。因此,您必须使用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;
}
public static extern int TestFunction();
public static extern int CleanUp();
static void Main(string[] args)
{
    Console.WriteLine("!!" + TestFunction());
    CleanUp();
}
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;
}
public static extern int TestFunction();
public static extern int CleanUp();
static void Main(string[] args)
{
    Console.WriteLine("!!" + TestFunction());
    CleanUp();
}

如果你重新定义新的操作符,为什么你的程序没有崩溃?! 实际上我不确定,但我认为,mingw的malloc实现使用HeapAlloc分配,HeapFree删除
test
变量。简言之,当您自定义新的
操作符并在内部使用
malloc
时,您只是幸运/不幸,它没有崩溃


但是,如果使用VisualStudio编译它,则(dll和exe)都使用相同的运行时,因此分配/取消分配是在相同的内存空间管理器中完成的仍然是UB,您将遇到问题!例如:如果您使用msvc10创建您的库,并且希望使用msvc14使用此库,同样的情况也会发生!我记得一些代码问题来自于一个错误,内存管理也错误;我们使用了一个用msvc11创建的库,但是我们的代码是用msvc12编译的…

我的意思是如果我想使用
new[]
。因此,如果我想使用
new[]
我要么必须重写
operator new[]
,要么必须使用Visual Studio编译.dll。为了澄清,我更改了这句话。我很清楚,从不同的编译器混合使用new/delete是危险的,但为什么我的示例代码在我只使用new[]时会崩溃操作员和完全不删除?另外,当我根本没有定义任何新的/删除运算符时,我希望使用来自同一个编译器的实现,因此不会出现崩溃…@kunzej UB是UB。如果您的代码尝试执行标准中未包含的操作,那么您不能对将发生的事情发表任何意见。
public static extern int TestFunction();
public static extern int CleanUp();
static void Main(string[] args)
{
    Console.WriteLine("!!" + TestFunction());
    CleanUp();
}