Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 诊断/调试潜在的堆栈损坏.NET应用程序_C#_.net_Winforms_Windbg_Memory Corruption - Fatal编程技术网

C# 诊断/调试潜在的堆栈损坏.NET应用程序

C# 诊断/调试潜在的堆栈损坏.NET应用程序,c#,.net,winforms,windbg,memory-corruption,C#,.net,Winforms,Windbg,Memory Corruption,我想我这里有一个卷曲的。。。我有一个WinForms应用程序,当作为x64进程运行时,它每隔一小时左右就会崩溃一次。我怀疑这是由于堆栈损坏造成的,我想知道是否有人见过类似的问题,或者对诊断和检测问题有什么建议 该程序没有可见的UI。它只是一个位于后台的消息窗口,充当其他客户端程序和服务器之间的“中间件” 它在不同的机器上以不同的方式死亡。有时是“APPCRASH”对话框报告ntdll.dll中的错误。有时是“APPCRASH”报告我们自己的dll是罪魁祸首。有时这只是一个无声的死亡。有时我们未处

我想我这里有一个卷曲的。。。我有一个WinForms应用程序,当作为x64进程运行时,它每隔一小时左右就会崩溃一次。我怀疑这是由于堆栈损坏造成的,我想知道是否有人见过类似的问题,或者对诊断和检测问题有什么建议

该程序没有可见的UI。它只是一个位于后台的消息窗口,充当其他客户端程序和服务器之间的“中间件”

它在不同的机器上以不同的方式死亡。有时是“APPCRASH”对话框报告ntdll.dll中的错误。有时是“APPCRASH”报告我们自己的dll是罪魁祸首。有时这只是一个无声的死亡。有时我们未处理的异常钩子会记录错误,有时则不会

在Windows错误报告起作用的情况下,我检查了几个不同崩溃场景中的内存转储,每次都在内存中发现相同的托管异常。这与我看到的报告为未经处理的异常的情况相同,即我们在它死亡之前记录它

我还很幸运(?)在使用Visual Studio进行调试时遇到了应用程序崩溃,并看到同样的异常导致程序崩溃

现在是踢球的人。这个特殊的异常在程序生命的最初几秒钟被抛出、捕获和吞没。我已经用额外的跟踪日志记录验证了这一点,并且在应用程序启动几分钟后对应用程序进行了内存转储,并验证了异常仍然存在于堆中的某个地方。我还对应用程序运行了内存分析器,并用它来验证没有其他.NET对象引用它

所讨论的代码看起来有点像这样(大大简化了,但保留了流控制的关键点)

现在。。。对我来说,这有点像堆栈腐败。在应用程序启动时引发并捕获异常。但指向它的指针在堆栈上存活了一个小时或更长时间,就像一颗子弹射入大脑一样,然后突然突破一条关键动脉,应用程序在水坑中死亡

额外线索:

  • “InternalFetch”中的代码使用了一些封送处理。[Alloc/Free]CoTask和pinvoke代码。我已经运行了FxCop来查找可移植性问题,但没有发现任何问题

  • 该问题的这种特殊表现形式只会影响在发布模式中内置的x64代码(启用代码优化)。我为“Place.Find”方法列出的代码反映了优化的.NET代码。未优化的代码将找到的对象作为最后一条语句返回,而不是“抛出异常”

  • 在上面的代码运行之前,我们在启动期间进行一些COM调用。。。在上述问题即将出现的场景中,第一个COM调用将失败。(例外情况被抓住并吞下)。我已经注释掉了那个特定的COM调用,它并没有阻止异常在堆上的出现

  • 该问题也可能会影响32位系统,但如果确实如此,则问题不会在同一位置出现。我只收到了几个像素的“应用程序崩溃”对话框的屏幕截图(典型用户!),但我能辨认出的一件事是故障模块字段中的“StackHash_2264”

编辑:

突破

我已将问题缩小到对
SetTimer
的特定调用。 pInvoke看起来像这样:

[DllImport("user32")]
internal static extern IntPtr SetTimer(IntPtr hwnd, IntPtr nIDEvent, int uElapse, TimerProc CB);

internal delegate void TimerProc(IntPtr hWnd, uint nMsg, IntPtr nIDEvent, int dwTime);
有一个特定的类在其构造函数中启动计时器。在构建该对象之前设置的任何计时器都可以工作。在构建该对象之后设置的任何计时器都可以工作。在构造过程中设置的任何计时器都会导致应用程序崩溃,这种情况更常见。(我的笔记本电脑有95%的时间会崩溃,但我的桌面电脑只有10%的时间会崩溃)

无论间隔设置为1小时还是1秒,似乎都没有什么不同。当计时器到期时,应用程序死亡——通常是通过抛出一些前面处理过的异常,如上所述。回调实际上不会执行。如果在构造函数返回后,在托管代码的下一行设置相同的计时器,那么一切都很好

当坏计时器即将启动时,我已经连接了一个调试器,它导致了“DispatchMessage”中的访问冲突。从未调用计时器回调。我已经启用了与被垃圾收集的托管回调相关的MDA,并且它不会触发。我用sos检查了对象,并验证了回调仍然存在于内存中,并且它指向的地址是正确的回调函数

如果我跑!此时,它通常(但不总是)会报告类似“ERROR\u SXS\u CORRUPT\u ACTIVATION\u STACK”的内容

用Microsoft的“System.Windows.Forms.Timer”类替换对SetTimer的调用也可以停止崩溃。我在类中使用了一个反射器,可以看到它在内部仍然调用SetTimer,但没有注册一个过程。相反,它有一个接收回调的本机窗口。这是pInvoke的定义实际上看起来是错误的。。。它对eventId使用“ints”,其中MSDN文档称它应该是一个UIntPtr

我们自己的代码最初也将“int”用于nIDEvent,而不是IntPtr——我在调查过程中对其进行了更改——但在声明更改之前和之后,崩溃仍在继续。所以我能看到的唯一真正的区别是我们正在注册回调,而Windows类没有

所以。。。在这个阶段,我可以通过将对SetTimer的一个特定调用转移到稍微不同的位置来“修复”这个问题。但我仍然没有真正理解在构造函数中启动计时器会导致此错误的特殊之处。我非常想了解这个问题的根源

Company.NotFoundException:
    Place.FindThing()
    AClass.FindAThing()
[DllImport("user32")]
internal static extern IntPtr SetTimer(IntPtr hwnd, IntPtr nIDEvent, int uElapse, TimerProc CB);

internal delegate void TimerProc(IntPtr hWnd, uint nMsg, IntPtr nIDEvent, int dwTime);