在IDE之外的Release模式下,使用x64 .NET 4.0应用程序崩溃

10

我遇到了一个非常奇怪的问题,我的测试应用程序会崩溃...非常严重。没有任何异常被抛出(至少没有我可以捕捉到的),只有“Blah Blah已停止响应”的消息。它只在x64,发布模式和IDE之外运行时崩溃。如果我在x86模式下运行它,在IDE中以x64运行它或者单独以x64调试运行它都是正常的。

我已经将问题缩小到我的p/invoke PeekMessage调用上。所以我需要这里伟大的头脑来看看我写的代码是否正确。因为,说实话,我快要疯了。我已经在两台计算机上尝试过了,它们都表现出相同的行为。我有些担心这可能是.NET 4.0的一个bug。

无论如何,这是我的p/invoke代码。如果你看到任何奇怪的东西或纯粹的愚蠢,请告诉我:

这是对PeekMessage的调用:

private static bool PeekMessage()
{
        MSG message = new MSG();                // Message to retrieve.

        return Win32API.PeekMessage(ref message, IntPtr.Zero, 0, 0, PeekMessageFlags.NoRemove);
}

这是 PeekMessage(注意:类定义上有抑制安全性属性,因此它正在被应用):

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool PeekMessage(ref MSG msg, IntPtr hwnd, uint wFilterMin, uint wFilterMax, PeekMessageFlags flags);

以下是MSG的内容:

[StructLayout(LayoutKind.Sequential)]
internal struct MSG
{
        /// <summary>Window handle.</summary>
        public IntPtr hwnd;
        /// <summary>Message to process.</summary>
        public uint Message;
        /// <summary>Window message parameter 1.</summary>
        public uint wParam;
        /// <summary>Window message parameter 2.</summary>
        public uint lParam;
        /// <summary>Time message was sent?</summary>
        public uint time;
        /// <summary>Mouse pointer position.</summary>
        public Point pt;
}

最后,PeekMessageFlags:

internal enum PeekMessageFlags
{
        /// <summary>Keep message on the message queue.</summary>
        NoRemove = 0,
        /// <summary>Remove message from the queue.</summary>
        Remove = 1,
        /// <summary>Do not yield execution to waiting threads.</summary>
        NoYield = 2
}

我查看了事件日志并得到了以下内容:

Faulting application name: Tester_Graphics.exe, version: 1.0.0.0, time stamp: 0x4ec0ba85
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x00000000000001cb
Faulting process id: 0x1260
Faulting application start time: 0x01cca299e2c21a77
Faulting application path: D:\Code\Current\Gorgon\Branches\2.x\Dorian\Examples\Tester_Graphics\bin\Release\Tester_Graphics.exe
Faulting module path: unknown
Report Id: 20ac891f-0e8d-11e1-a5d7-bcaec5753ddd

如果你发现任何不太对的地方,请告诉我。我希望这不是我的错。

如果这不够详细,很抱歉。如果需要更多信息,请留言。


1
我曾经遇到过类似的问题,即使是最微小的参数错误,特别是字符串(Unicode vs. Ansi等)。这个页面列出了PeekMessage的不同签名。我建议您尝试几个其他签名,直到找到一个可行的。 - Uwe Keim
2
作为一个随机的提示,如果您在调试时遇到了问题,那么它很可能会引发异常。假设您构建程序后可以加载它,您可以运行它。然后,通常的Visual Studio附加到进程,只要PDB与之匹配,您就可以在发布模式下调试它。然后您可以打开任何抛出的异常断点(CTRL+ALT+E),这样您可能会获得更多信息。 - Chris Marisic
是的,我考虑过这样做,但它立即出现了异常,所以没有时间附加。我现在意识到,在PeekMessage之前可以添加一个“Sleep”延迟,但当时已经是午夜了,我几乎无法组织连贯的句子,所以当时没有想到。 - Mike
1个回答

6
MSGlParamwParam 字段的大小是错误的。您应该使用 IntPtr 而不是 uint / int
如果您查看 Windows 数据类型,您会发现:
- LPARAM 是一个 LONG_PTR,在 32 位平台上为 32 位,在 64 位平台上为 64 位。 - WPARAM 是一个 UINT_PTR,在 32 位平台上为 32 位,在 64 位平台上为 64 位。
相反,intuint 类型的大小均为 32 位,无论平台如何,这意味着在 64 位平台上,您的 MSG 结构体也要小 64 位,这将导致某种内存损坏。

2
是的,Uwe Keim建议我访问pinvoke.net后,我刚看到这个。昨晚我已经做过了。我将其更改为“IntPtr”,它就像魔法一样奏效了。所以谢谢你们两个。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接