从分段错误中恢复的最佳实践
Best practices for recovering from a segmentation fault
我正在研究一个用c++编写的多线程进程,并且正在考虑使用google- coreddump修改SIGSEGV处理,以便在发生分段错误时保持进程存活。
然而,google- coreddump的这种用法似乎很有可能陷入核心转储的无限循环,除非我以某种方式重新初始化可能导致核心转储的线程和对象。
在尝试通过核心转储保持流程活动时,我应该记住哪些最佳实践?我还应该注意哪些"陷阱"?
谢谢!
这实际上在c中是可能的。你可以用一种相当复杂的方式实现它:
1)覆盖信号处理程序
2)使用setjump()
和longjmp()
设置跳回的位置,并实际跳回那里。
看看我写的这段代码(灵感来自Peter Van Der Linden的"Expert C Programming: Deep C Secrets"):
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
//Declaring global jmp_buf variable to be used by both main and signal handler
jmp_buf buf;
void magic_handler(int s)
{
switch(s)
{
case SIGSEGV:
printf("nSegmentation fault signal caught! Attempting recovery..");
longjmp(buf, 1);
break;
}
printf("nAfter switch. Won't be reached");
}
int main(void)
{
int *p = NULL;
signal(SIGSEGV, magic_handler);
if(!setjmp(buf))
{
//Trying to dereference a null pointer will cause a segmentation fault,
//which is handled by our magic_handler now.
*p=0xdead;
}
else
{
printf("nSuccessfully recovered! Welcome back in main!!nn");
}
return 0;
}
最佳做法是修复导致核心转储的原始问题,重新编译,然后重新启动应用程序。
要在野外部署之前捕获这些错误,请进行大量的同行评审并编写大量的测试。
Steve的答案实际上是一个非常有用的公式。我在一个复杂的嵌入式软件中使用了类似的东西,其中至少有一个SIGSEGV错误,我们无法通过发货时间来追踪。只要您可以重置代码,使其不会产生不良影响(内存或资源泄漏),并且错误不会导致无休止的循环,它就可以拯救生命(即使修复错误更好)。仅供参考,在我们的情况下,它是单线程的。
但是忽略的是,一旦您从信号处理程序中恢复,它将无法再次工作,除非您揭开信号的掩码。下面是一段代码:
sigset_t signal_set;
...
setjmp(buf);
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
// Initialize all Variables...
确保释放内存、套接字和其他资源,否则发生这种情况时可能会泄漏内存。
我对分段错误的经验是很难移植地捕获它们,而在多线程上下文中移植它几乎是不可能的。
这是一个很好的理由:你真的希望在SIGSEGV之后内存(线程共享的)是完整的吗?毕竟,您刚刚证明了一些寻址被破坏了,所以假设其余的内存空间是干净的是相当乐观的。
考虑不同的并发模型,例如进程。进程不共享它们的内存,或者只共享内存的一部分(共享内存),当另一个进程死亡时,一个进程可以合理地继续工作。当你有一个程序的关键部分(例如核心温度控制),把它放在一个额外的进程保护它免受内存损坏的其他进程和分段错误。
如果出现分段错误,您最好放弃该过程。在此之后,您如何知道进程的任何内存都是可用的?如果你的程序中有什么东西扰乱了内存,它不应该,为什么你相信它没有扰乱内存的其他部分,你的进程实际上可以访问没有分段故障?
我认为这样做将主要有利于攻击者。
从coreddump的描述来看,它的目的似乎不是你想要的,而只是允许对进程内存进行快照。
就我个人而言,我不会在进程触发核心转储后保留它——它有很多可能被破坏的方式——并且会使用一些持久性来允许在进程重新启动后恢复数据。
是的,正如parapura所建议的,更好的是找出导致SIGSEGV的原因并修复它。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在c代码之间共享数据的最佳方式
- 使用std::source_location报告错误的最佳实践
- 派生类销毁的最佳实践是什么
- 用C++将哈希表写入文件并从文件中恢复
- 将寄存器设计成可由C和C++访问的外设的最佳实践
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 检测win32服务创建和删除的最佳方法
- 在reactor中存储eventHandlers的最佳方式是什么
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 暂停和恢复线程的最佳解决方案是什么?
- 从分段错误中恢复的最佳实践
- 创建可挂起/可恢复线程的最佳方法是什么?