【问题标题】:handler specified by signal() was not called未调用由 signal() 指定的处理程序
【发布时间】:2018-08-29 09:11:20
【问题描述】:

我正在尝试在 Win32/C++ 程序中打印调用堆栈。

this 文章中,我学到了一种在访问冲突时调用我的处理程序的方法。但是,这似乎只适用于简单的控制台程序。

在我将相同的代码复制到带有消息泵的 win32 程序中后,我的处理程序没有被调用。

我认为钩子安装部分是一样的,唯一的区别是触发访问冲突的邪恶代码不是在处理程序安装后立即调用,而是从处理程序安装中抽出几个消息。

有没有人暗示为什么我的处理程序没有被调用?

让我试着解释一下我的代码:

void SignalHandler_SegmentViolation(int signal)
{
    StackWalker sw;
    sw.ShowCallstack();
    throw "!Access Violation!";
}
void someFuncionCalledUponButtonClick()
{
    *(int*)0x00 = 5;
}
void myMsgPump()
{
    while(TRUE)
    {
        GetMessage(&msg, NULL, 0, 0);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
{
    typedef void (*SignalHandlerPointer)(int);

    SignalHandlerPointer previousHandler;
    previousHandler = signal(SIGSEGV , SignalHandler_SegmentViolation);

    try
    {
        myMsgPump();
    }
    catch(char *e)
    {
        printf("Exception Caught: %s\n",e);

        // return control to default handler
        previousHandler(SIGSEGV);
    }
}

【问题讨论】:

  • 我会说你正在做的事情是糟糕的! 信号处理程序不像代码中的普通函数那样被调用,现在抛出异常可能会起作用或甚至是明确定义(或完全定义)。
  • 当引发未捕获的异常时,代码看起来像您正在尝试收集诊断信息。您可能想查看MiniDumpWriteDump,而不是使用某种堆栈遍历代码。这将生成更多有价值的信息,并且不需要您发送 PDB 文件。还要查看SetUnhandledExceptionFilter,这就是你应该使用的。
  • @IInspectable 非常感谢!!

标签: c++ winapi exception signals handler


【解决方案1】:

在 Windows 上,信号系统及其支持功能是与 POSIX(Linux 或 macOS 等类 Unix 系统)的小型兼容性层的一部分。因此,许多 POSIX 标准信号并未真正实现且不起作用。

其中一个在 Windows 中不起作用的信号是分段错误信号SIGSEGV

控制台层(CRT)是 WIN32 系统之上的一个层,可能实现了某些信号。还有其他 POSIX 兼容系统(例如 Cygwin)也有自己的信号实现。对于直接的 WIN32 程序,没有这样的兼容性。

【讨论】:

  • 我是否有机会做某事,例如在访问冲突时打印调用堆栈?
  • SetUnhandledExceptionFilter API 允许客户端代码将回调函数链接到异常处理过程中。回调方便地接收EXCEPTION_POINTERS 结构,可用于后续调用MiniDumpWriteDump 以在引发异常时保留调用堆栈。
  • 虽然这看起来是完美的解决方案,但在纸面上,系统可能会妨碍您。具体来说,在某些情况下,系统会抑制 WindowProc 回调引发的未捕获异常。另请注意,SEH 异常处理和 C++ 异常处理不一定能很好地混合。
  • Windows C 运行时使用结构化异常处理程序来实现SIGSEGV(即STATUS_ACCESS_VIOLATION)、SIGILL(即STATUS_ILLEGAL_INSTRUCTIONSTATUS_PRIVILEGED_INSTRUCTION)和SIGFPE(即@ 987654332@等)。这些是标准 C 所需的 6 个信号中的 3 个。它们在 GUI 应用程序中受支持,但在某些情况下可能不会调用 CRT 的异常处理程序。
  • VC++ 异常是使用系统异常框架实现的(例如RaiseException)。有一些方法可以在 C++ try/catch(与 __try/__except 相对)中集成系统异常(通常称为“异步”,但这是用词不当),但并不鼓励。此外,如前所述,由系统组件(如窗口管理器)调用的函数可能由不链接到应用程序处理程序的异常处理程序保护。系统可能会处理或忽略异常,或者干脆终止应用程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
相关资源
最近更新 更多