【问题标题】:Stack Imbalance堆栈不平衡
【发布时间】:2016-05-06 09:43:49
【问题描述】:

对 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

【问题讨论】:

  • 来自MSDN: BOOL WINAPI ReleaseCapture(void); 不需要参数。
  • 是的,您可以将它用于拖动功能。您可以在 mousedown 事件上然后发送一条消息,它代表事件...pinvoke.net/default.aspx/user32.releasecapture
  • 有人能解释一下否决票吗?所以我可以编辑我的问题...
  • 如果您浏览 Related 下的一些条目,您会发现它们都有相同的源问题:whacky params(好吧,反正我看过的 3 个)

标签: vb.net pinvoke clr


【解决方案1】:

正确的签名是这样的:

<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。你的程序一直都是错误的,你很幸运。现在您使用了更好的工具,该工具已经能够通知您您的错误。

【讨论】:

  • 我已经看过这些了,这不是问题。我说它已经工作了6年......
  • 不,这是问题所在。您的代码已经错误了 6 ​​年。你能阅读我链接到的文档吗?还是你认为自己比 MSDN 更了解?
  • 请睁开眼睛。请阅读我链接到的文档。像这样传递额外参数的堆栈不平衡不一定会导致错误,因为 p/invoke 机制恰好掩盖了您的错误。但是您的代码是错误的,我的答案中的代码是正确的。鉴于可以在 MSDN 文档中如此清楚地看到的事实,我无法想象你为什么会否决这个答案。
  • 我知道签名是什么。这是我做的第一件事。使用 Ants Profiler,我发现一些内存问题与不使用我的控件句柄来释放委托事件有关。
  • 有人改变了一些东西,但不太确定......仍在深入研究。
猜你喜欢
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
  • 2014-03-13
相关资源
最近更新 更多