c++ - 如何用断言做一些有用的事情?

标签 c++ signals assert abort

我想用 assert 做一些比 abort 更有用的事情,包括刷新一些打开的文件和打印堆栈跟踪。

我读了一些关于 assert 的文章,比如 Assertions by Andrei Alexandrescu其中讨论了如何实现断言。但是,即使在我的程序使用的第三方库中,我也想用我自己的断言处理程序替换。我了解我使用的大多数(但不是全部)编译器(gcc、MSVC、clang)和库(Qt、boost)都有设置用户定义断言处理程序的选项。但是目前我对断言的 Abort,Retry,Ignore 特性不感兴趣,因此不在编译器/库特定的断言处理程序中查看我的代码。

据我所知,assert 调用 abort 发送 SIGABRT 信号,我可以捕获该信号并执行有用的任务吗?

最佳答案

用你自己的实现劫持 assert() 怎么样?在 Unix 系统上,您可以使用 LD_PRELOAD trick劫持 __assert_fail(assert() 本身只是一个调用后者的宏)。

另一种可能性是按照您的建议捕获 SIGABRT。但是我看到了一些要求:

  1. 一种区分对 assert() 的调用与接收到 SIGABRT 的其他可能原因的方法。这可能是来自另一个线程或进程的 kill() 调用,甚至是来自堆管理函数完整性检查的 abort() 本身的调用( free(), malloc() ...)。这可以通过 ABRT 信号处理程序来完成,通过检查进程的执行堆栈或在某些系统中传递给 sigaction() 的上下文(没有人知道如何使用 void* 参数)。

  2. 如果您决定捕获 SIGABRT,您应该牢记 signal handlers are not "legally" allowed to do much (甚至没有调用 printf),这使他们成为不适合按照您的要求做“更有用的事情”的人选。

    所以最好有一个专门的线程永久等待 对于带有 sigwait() 的信号(基于 abort() 的方式 实现这可能不是一个选项)或由信号通知 每当收到信号时处理程序 ao 它可以执行大部分操作 信号处理程序上下文的工作。

    此外,重要的是要注意,如果在其实现中,SIGABRT 由 abort() 专门发送到其调用线程,那么它的接收将是同步的,您可以自由调用异步 -不安全的函数。

  3. 通过自己捕获信号并修改线程的信号掩码,您可能会影响您提到的那些第三方库的信号行为(它们可能会自己捕获 SIGABRT)。 p>

  4. 即使您使用自己的信号处理程序捕获 SIGABRT,您也无法返回正常执行信号是从对 abort() 的调用发送的,因为(引自 alarm(8 )):

If the SIGABRT signal is ignored, or caught by a handler that returns, the abort() function will still terminate the process. It does this by restoring the default disposition for SIGABRT and then raising the signal for a second time.

关于c++ - 如何用断言做一些有用的事情?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14868578/

相关文章:

c++ - 模板特化 - clang 和 gcc 的不同结果

c++ - 将外部事件循环与 Qt 相结合

c++ - 在双重检查锁定模式中获取屏障

bash - 我可以在用户按下 Control-C 后强制 MATLAB 退出吗?

java - 为什么在类初始化之前执行的断言语句的行为就像在类中启用了断言一样?

postman - 即使任何一个断言失败,有没有办法继续在 postman 中进行测试?

c++ - 对仅在断言中使用的变量使用 [[maybe_unused]] 是否有缺点?

c++ - 重新配置现有对象而不是替换它们的循环缓冲区?

algorithm - 如何从matlab中的差分方程中找到非因果向量?

c - posix 线程阻塞信号和解除阻塞