可能导致std::difftime创建SIGBUS崩溃的原因
What could cause std::difftime to create a SIGBUS crash?
今天,我不得不惊恐地意识到,我的C++模拟程序在运行了12天后崩溃了,就在它结束前的几行,只剩下一个(截断的)核心转储。
gdb对堆芯转储的分析表明,
程序终止,信号为SIGBUS,总线错误。
崩溃发生在我代码的以下行:
seconds = std::difftime(stopTime, startTime); // seconds is of type double
变量stopTime
和startTime
属于std::time_t
类型,我能够在崩溃时从堆芯转储中提取它们的值:
startTime: 1426863332
stopTime: 1427977226
difftime调用上方的堆栈跟踪如下所示:
#0 0x.. in _dl_fixup () from /lib64/ld-linux-x86-64.so.2
#1 0x.. in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2
我写了一个小程序来重现错误,但没有成功。仅使用上述值调用std::difftime(stopTime, startTime)
不会导致SIGBUS崩溃。当然,我不希望这种情况再次发生。我以前曾多次成功地执行相同的程序(尽管参数不同),执行时间相当。是什么原因导致了这个问题,我如何在将来防止它?
以下是一些附加的系统信息。
GCC: (SUSE Linux) 4.8.1 20130909 [gcc-4_8-branch revision 202388]
Linux Kernel: 3.11.10-25-desktop, x86_64
C++ standard library: 6.0.18
编辑
以下是更多的上下文。首先,完整的堆栈跟踪(省略号[..]
mine):
#0 0x00007f309a4a5bca in _dl_fixup () from /lib64/ld-linux-x86-64.so.2
#1 0x00007f309a4ac195 in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2
#2 0x0000000000465453 in CStopwatch::getTime (this=0x7fff0db48c60, delimiterHourMinuteSecondsBy="") at [..] CStopwatch.cpp:86
#3 0x00000000004652a9 in CStopwatch::stop (this=0x7fff0db48c60) at [..] CStopwatch.cpp:51
#4 0x0000000000479a0c in main (argc=33, argv=0x7fff0db499c8) at [..] coherent_ofdm_tsync_mse.cpp:998
该问题发生在程序开始时创建的CStopwatch
类对象中。秒表在main()中最顶部启动。仿真完成后,调用函数CStopwatch::stop( )
。
秒表类的构造函数:
/*
* Initialize start and stop time on construction
*/
CStopwatch::CStopwatch()
{
this->startTime = std::time_t( 0 );
this->stopTime = std::time_t( 0 );
this->isRunning = false;
}
函数CStopwatch::stop( )
/*
* Stop the timer and return the elapsed time as a string
*/
std::string CStopwatch::stop( )
{
if ( this->isRunning ) {
this->stopTime = std::time( 0 );
}
this->isRunning = false;
return getTime( );
}
函数CStopwatch::getTime()
/*
* Return the elapsed time as a string
*/
std::string CStopwatch::getTime( std::string delimiterHourMinuteSecondsBy )
{
std::ostringstream timeString;
// ...some string init
// time in seconds
double seconds;
if ( this->isRunning ){
// return instantaneous time
seconds = std::difftime(time(0), startTime);
} else {
// return stopped time
seconds = std::difftime(stopTime, startTime); // <-- line where the
// program crashed
}
// ..convert seconds into a string
return timeString.str( );
}
在程序开始时,CStopwatch::start( )
被称为
/*
* Start the timer, if watch is already running, this is effectively a reset
*/
void CStopwatch::start( )
{
this->startTime = std::time( 0 );
this->isRunning = true;
}
程序在Linux上接收SIGBUS
的原因只有几个。这个问题的答案中列出了几个。
查看崩溃前后的/var/log/messages
,您可能会发现存在磁盘故障,或者其他导致内核不愉快的原因。
另一种(不太可能的)可能性是,有人在程序运行时更新了libstdc++.so.6
,但操作不正确(通过重写现有文件,而不是删除它并在其位置创建新文件)。
看起来std::difftime
在第一次访问时被延迟加载;如果运行时链接器的某些内部状态已在程序的其他地方损坏,则可能会导致这种情况。
请注意,_dl_runtime_resolve
必须在std::difftime
调用开始之前完成,因此错误不太可能与您的时间值有关。您可以通过打开gdb:中的核心文件来轻松验证
(gdb) frame 2 # this is CStopwatch::getTime
(gdb) print this
(gdb) print *this
etc. etc.
如果gdb能够读取并解析地址,并且这些值看起来正常,那么在运行时肯定不会导致SIGBUS。或者,你的堆栈可能被砸碎了;如果CCD_ 17正在准备蹦床跳跃而不仅仅是处理重新定位等。;如果不看代码,我们就无法确定,但可以检查堆栈本身:
(gdb) print %rsp
(gdb) x/16xb $rsp-16 # print the top 16 bytes of the stack
尝试的简单解决方法是设置LD_BIND_NOW
环境变量并在启动时强制符号解析。不过,这只是隐藏了问题,因为一些内存仍在的某个地方受损,而我们只是隐藏了症状。
至于正确修复问题——即使短时间运行没有显示错误,也可能发生了一些内存损坏,但没有症状。尝试在valgrind下运行一个较短的模拟,并修复所有警告和错误,除非你确定它们是良性的。
如果没有进一步的上下文,就无法判断,但是:
this
可能是null
或已损坏startTime
可能是空引用stopTime
可能是空引用
我本来打算建议您在行上设置一个断点并打印出stopTime
和startTime
,但通过查看核心文件,您已经几乎做到了这一点。
链接中的函数似乎出了问题。可能是您正在根据链接到的标准库中的一组不同的头进行编译吗?
它可能只是与内存有关:
- 如果这是深度嵌套的,那么可能只是出现堆栈溢出
- 如果这是第一次调用它,也许它正试图为库分配内存、加载并链接它,但由于达到内存限制而失败
如果这个代码路径被多次调用,并且从未在其他地方崩溃,那么也许是时候通宵运行memtest86
了。
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 在虚幻引擎中删除NXOpen对象时崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Visual Studio在尝试读取resource.txt文件时崩溃
- 可能导致std::difftime创建SIGBUS崩溃的原因