Mat*_*ias 2 .net c# stack-overflow dllimport
我目前正在进行微基准测试,以便更好地理解clr到本机代码的性能.在下面的例子中,我得到一个StackOverflowException,当编译为release并执行时没有连接调试器.编译为debug-build或运行附带调试器的程序时,我没有得到异常.此外,我也只使用SuppressUnmanagedCodeSecurityAttribute-Attribute 获得此错误.
我使用c和VS2013(platformtoolset = v120)构建了一个dll,其中包含一个函数:
__declspec(dllexport) int __cdecl NativeTestFunction(int a, int b, int c, int d)
{
return a + c + b + d;
}
Run Code Online (Sandbox Code Playgroud)
在我的C#程序中,我DllImport用来调用这个函数并进行一些时序测量:
[DllImport("Native.dll", EntryPoint = "NativeTestFunction")]
static extern int NativeTestFunction(int a, int b, int c, int d);
[DllImport("Native.dll", EntryPoint = "NativeTestFunction"), SuppressUnmanagedCodeSecurityAttribute]
static extern int NativeTestFunctionSuppressed(int a, int b, int c, int d);
static void Main(string[] args)
{
byte[] data = new byte[64];
int c = 0;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
c += NativeTestFunction(2, -1, -2, 1);
Console.WriteLine("Unsuppressed: " + sw.Elapsed.ToString());
sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
c += NativeTestFunctionSuppressed(2, -1, -2, 1);
Console.WriteLine("Suppressed..: " + sw.Elapsed.ToString());
}
Run Code Online (Sandbox Code Playgroud)
如果我将此代码编译为release并在没有附加调试器的情况下启动它,则输出为:
Unsuppressed: 00:00:00.2666255
Process is terminated due to StackOverflowException.
Run Code Online (Sandbox Code Playgroud)
但是,在调试器附加或编译为调试的情况下执行,并且无论是否附带调试器启动,程序都会成功:
Unsuppressed: 00:00:00.2952272
Suppressed..: 00:00:00.1278980
Run Code Online (Sandbox Code Playgroud)
这是.NET/CLR中的已知错误吗?我的错是什么?我认为附加和未附加的调试器之间的行为应该是相同的.
.NET 2.0和.NET 4.0发生此错误.我的软件编译为x86(因此仅针对x86进行测试)以兼容Native.dll.如果您不想自己设置此方案,可以下载我的测试项目:源代码.
__declspec(dllexport) int __cdecl NativeTestFunction(int a, char* b, int c, int d)
Run Code Online (Sandbox Code Playgroud)
注意类型b.是的char*.然后在你编写的C#代码中:
[DllImport("Native.dll", EntryPoint = "NativeTestFunction"),
SuppressUnmanagedCodeSecurityAttribute]
static extern int NativeTestFunctionSuppressed(int a, int b, int c, int d);
Run Code Online (Sandbox Code Playgroud)
在这里你声明b是int.那不匹配.调用该函数时会变得更糟.
NativeTestFunctionSuppressed(2, -1, -2, 1);
Run Code Online (Sandbox Code Playgroud)
-1在32位进程中传递将等同于传递地址0xffffffff.尝试取消引用该地址没有任何好处.
另一个问题是调用约定不匹配.本机代码使用__cdecl,但托管代码使用默认值__stdcall.将托管代码更改为:
[DllImport("Native.dll", EntryPoint = "NativeTestFunction",
CallingConvention = CallingConvention.Cdecl),
SuppressUnmanagedCodeSecurityAttribute]
Run Code Online (Sandbox Code Playgroud)
同样对于其他进口.
| 归档时间: |
|
| 查看次数: |
492 次 |
| 最近记录: |