堆栈不平衡

Stack Imbalance

A call to PInvoke function 'ReleaseCapture' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

这个函数就是这样定义的,并且已经运行了 6 年多了。直到用户报告,我们才得知此错误。当用户开始在屏幕上拖动用户控件时会发生这种情况,如果不拖动它就可以了。

  <DllImport("user32")> _
  Public Shared Function ReleaseCapture(ByVal hwnd As IntPtr) As Integer
  End Function

此函数在用户控件 MouseDown 事件上调用。例如:

  Private Sub uxCalcTitleBar_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles uxCalcTitleBar.MouseDown, lblCalcTitle.MouseDown
    If e.Button = Windows.Forms.MouseButtons.Left And e.Clicks = 1 Then
        If Not Me._CalcIsMoving And Not Me._CalcIsPackedForMove Then
            Me.Calc_PackForMove()
        End If
        ReleaseCapture(Me.uxCalculator.Handle) **ERROR HERE**
        SendMessage(Me.uxCalculator.Handle, WM_SYSCOMMAND, MOUSE_MOVE, 0)
        Me._CalcNewLocation = Me.uxCalculator.Location

        Me.uxCalcTitleBar_MouseUp(sender, e)
    End If
End Sub

我们注意到一件事,从 2.0 迁移到 4.5 框架后开始发生这种情况。不知道这是否有所作为,但我认为应该不会。经过一些研究,我发现解决方案应该是审查托管平台调用签名和调用约定,以确认它与本机目标的签名和调用约定相匹配。

我试过的

我检查了签名,它似乎很好,实际上什么也看不到。我还指定了这样的约定来清除它没有帮助的堆栈...

  <DllImport("user32", CallingConvention:=CallingConvention.Cdecl)> _
  Public Shared Function ReleaseCapture(ByVal hwnd As IntPtr) As Integer
  End Function

正确的签名是这样的:

<DllImport("user32.dll")> _
Public Shared Function ReleaseCapture() As Boolean
End Function

该函数不带任何参数,从文档中可以看出:https://msdn.microsoft.com/en-us/library/windows/desktop/ms646261.aspx

关于您对 CallingConvention.Cdecl 的使用,这是一个错误。调用约定是 CallingConvention.StdCall,这是默认值,因此可以省略。您不必决定调用约定是什么,就像您无法决定参数是什么一样。您不能决定强加 CallingConvention.Cdecl 作为“清除堆栈”的手段。那是毫无意义的。函数的实现者决定了它的调用约定、参数等。你的工作是满足功能实现者指定的接口契约。


One thing we noticed, this started happening after moving to the 4.5 framework from 2.0.

确实如此。 .net 的 2.0 版不包含产生此消息的 pInvokeStackImbalance MDA。您的程序一直都是错误的,您很幸运。现在您正在使用更好的工具,该工具已经能够通知您您的错误。