挂钩 SetConsoleCtrlHandler 时没有堆栈跟踪的 NullReferenceException

发布于 2024-11-25 12:43:58 字数 1106 浏览 1 评论 0原文

使用代码从此线程挂钩控制台关闭事件,我有时会得到NullReferenceException 没有堆栈跟踪(大多数时候我没有)。它发生在发布和调试中,并且“抛出异常时中断”没有帮助(它中断,但堆栈跟踪仍然为空)。当我正常退出应用程序时(按下回车键并因此释放Console.ReadLine),我从未遇到此异常。应用程序事件日志有 2 个条目:

应用程序:MyApp.exe 框架版本:v4.0.30319 描述: 由于未处理的异常,该进程被终止。例外 信息:System.NullReferenceException 堆栈:

并且:

故障应用程序名称:Gateway.exe,版本:1.0.0.0,时间戳: 0x4e284101 故障模块名称:未知,版本:0.0.0.0,时间 标记:0x00000000 异常代码:0xc0000005 故障偏移量:0x004d41ce 错误进程 ID:0xf00 错误应用程序启动时间: 0x01cc47b827e19a6e 错误的应用程序路径: C:\dev\MyApp.exe 错误模块路径: 未知报告 ID:689c1caa-b3ab-11e0-ba1b-00247e777f12

Google 已透露一些 错误问题SetConsoleCtrlHandler,所以我想知道这是否是一场失败的战斗。

Using code to hook the console close event from this thread, I sometimes get a NullReferenceException with no stacktrace (most of the times I don't). It happens in both release and debug and "break when an exception is thrown" doesn't help (it breaks, but the stack trace is still empty). I never get this exception when I exit my application normally (which is hitting enter and thus releasing a Console.ReadLine). The Application event log has 2 entries:

Application: MyApp.exe Framework Version: v4.0.30319 Description:
The process was terminated due to an unhandled exception. Exception
Info: System.NullReferenceException Stack:

And:

Faulting application name: Gateway.exe, version: 1.0.0.0, time stamp:
0x4e284101 Faulting module name: unknown, version: 0.0.0.0, time
stamp: 0x00000000 Exception code: 0xc0000005 Fault offset: 0x004d41ce
Faulting process id: 0xf00 Faulting application start time:
0x01cc47b827e19a6e Faulting application path:
C:\dev\MyApp.exe Faulting module path:
unknown Report Id: 689c1caa-b3ab-11e0-ba1b-00247e777f12

Google has revealed some bugs and issues with SetConsoleCtrlHandler, so I'm wondering if this is a lost battle.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仅冇旳回忆 2024-12-02 12:43:58

此类代码最典型的问题是没有保留对委托实例的引用。作为第一个参数传递给 SetConsoleCtrlHandler() 的那个。垃圾收集器无法看到非托管代码对委托对象的引用。因此,当垃圾收集器运行时,这最终会爆炸:

 SetConsoleCtrlHandler(Handler, true);

完全相同

 SetConsoleCtrlHandler(new EventHandler(Handler), true);

这与假设您使用链接代码中的类型 。该代码的作者通过将 _handler 设置为静态变量来小心地避免了这个问题。与前两行代码创建的临时委托实例相反。将其存储在静态变量中可确保它在程序的生命周期内保持引用状态。在这种特殊情况下,正确的做法是因为您实际上对节目结束之前的事件感兴趣。

The most typical issue with code like that is not keeping a reference to the delegate instance. The one you pass as the first argument to SetConsoleCtrlHandler(). The garbage collector cannot see references held to a delegate object by unmanaged code. So this will, eventually, bomb when the garbage collector runs:

 SetConsoleCtrlHandler(Handler, true);

which is the exact same thing as

 SetConsoleCtrlHandler(new EventHandler(Handler), true);

assuming you used the types in the linked code. The author of that code carefully avoided this issue by making _handler a static variable. As opposed to the temporary delegate instance that is created by the previous two lines of code. Storing it in a static variable ensures it stays referenced for the life of the program. The Right Thing to do in this particular case since you are actually interested in the events until the program ends.

左岸枫 2024-12-02 12:43:58

对于正在为此苦苦挣扎的 vb.net 用户,我的代码是......

'declaration
Private Declare Function SetConsoleCtrlHandler Lib "kernel32" (ByVal handlerRoutine As ConsoleEventDelegate, ByVal add As Boolean) As Boolean
Public Delegate Function ConsoleEventDelegate(ByVal [event] As ConsoleEvent) As Boolean

'The close function...
Public Function Application_ConsoleEvent(ByVal [event] As ConsoleEvent) As Boolean
    Console.WriteLine("We're closing it all down: ")
    Return False
End Function

'creating the handler. 
If Not SetConsoleCtrlHandler(New ConsoleEventDelegate(AddressOf Application_ConsoleEvent), True) Then
    Console.WriteLine("Unable to install console event handler.")
    Exit Sub
End If

For the vb.net bods who are struggling with this, my code is ...

'declaration
Private Declare Function SetConsoleCtrlHandler Lib "kernel32" (ByVal handlerRoutine As ConsoleEventDelegate, ByVal add As Boolean) As Boolean
Public Delegate Function ConsoleEventDelegate(ByVal [event] As ConsoleEvent) As Boolean

'The close function...
Public Function Application_ConsoleEvent(ByVal [event] As ConsoleEvent) As Boolean
    Console.WriteLine("We're closing it all down: ")
    Return False
End Function

'creating the handler. 
If Not SetConsoleCtrlHandler(New ConsoleEventDelegate(AddressOf Application_ConsoleEvent), True) Then
    Console.WriteLine("Unable to install console event handler.")
    Exit Sub
End If
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文