【发布时间】:2015-06-09 13:51:46
【问题描述】:
我目前正在做微基准测试,以便更好地了解 clr 到本机代码的性能。在以下示例中,当编译为发行版并在未附加调试器的情况下执行时,我得到了一个StackOverflowException。编译为 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;
}
在我的 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());
}
如果我将此代码编译为发行版并在没有附加调试器的情况下启动它,则输出为:
Unsuppressed: 00:00:00.2666255
Process is terminated due to StackOverflowException.
但是,在附加调试器的情况下执行或编译为调试并在附加或不附加调试器的情况下启动程序都会成功:
Unsuppressed: 00:00:00.2952272
Suppressed..: 00:00:00.1278980
这是 .NET/CLR 中的已知错误吗?我的错误是什么?我认为附加和未附加调试器之间的行为应该是相同的。
此错误发生在 .NET 2.0 和 .NET 4.0 中。我的软件编译为 x86(因此仅针对 x86 进行了测试)以兼容 Native.dll。如果你不想自己设置这个场景,你可以下载我的测试项目:Sourcecode。
【问题讨论】:
-
您的声明是错误的,缺少的 CallingConvention = CallingConvention.Cdecl 使堆栈失衡。是的,当您在没有调试器的情况下运行 Release 构建并且代码优化器可以发挥它的魔力时,这很容易被炸毁。您应该已经收到警告,请确保您没有关闭 PInvokeStackImbalance 调试器助手。
-
抱歉重复了。在询问时我不知道 __cdecl/__stdcall 是问题所在。
标签: c# .net stack-overflow dllimport