堆栈失衡

时间:2016-01-28 20:21:16

标签: vb.net pinvoke clr

  

对PInvoke函数'ReleaseCapture'的调用使堆栈失衡。   这可能是因为托管的PInvoke签名不匹配   非托管目标签名。检查调用约定和   PInvoke签名的参数与目标非托管签名匹配。

这个功能已经用这种方式定义,已经工作了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

1 个答案:

答案 0 :(得分:3)

正确的签名是:

<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作为“清除堆栈”的方法。那毫无意义。函数的实现者决定其调用约定,参数等。您的工作是满足函数实现者指定的接口契约。

  

我们注意到一件事,这是从2.0迁移到4.5框架后开始发生的。

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