程序崩溃时流的C++行为

behavior of C++ ofstream in the event of program crash

本文关键字:C++ 行为 崩溃 程序      更新时间:2023-10-16

我正在尝试调试一个运行时错误,该错误导致我的程序在执行过程中冻结。我创建了一个日志系统,在执行过程中编写一个简单的日志文本文件。

我只需使用带有std::string类型消息的ofstream对象的流插入(<<)运算符就可以将信息写入日志文件。

void foo(){
// ... Code block 1 ...
// myLogger.Write (timestamp, "Code block1 successfully executed");
// ... Code block 2 ... PROGRAM FREEZE AND CRASH!
}

我的问题是:假设我的程序冻结了,我需要从任务管理器中终止它的进程,我能相信我的日志系统在崩溃点之前已经可靠地写入了所有消息吗?

或者,参考上述代码,如果代码块2导致我的程序冻结,我能相信"代码块1成功执行"消息在任何情况下都会出现在我的日志文件中吗?

附言:我在Windows上,我感到担心的原因是,在某些奇怪的情况下,我不完全信任操作系统在文件权限方面的行为。我的程序确实有对该文件的读/写权限,但我不知道在崩溃期间会发生什么奇怪的事情。也许我只是多疑,如果是,请告诉我。

有没有更好的方法来检测崩溃发生在哪个代码块中?

"我能相信"代码块1成功执行"消息在任何情况下都会出现在我的日志文件中吗?"

不,当执行该语句时,您不能相信任何东西最终都会写入日志文件,而您的程序实际上处于某种异常状态。

由于flush()调用隐含了要写入的行,所以机会会更好,但仍然无法保证。这取决于您的程序所满足的特殊条件。

考虑一种情况,您的程序由于未定义的行为而崩溃,该行为意外地弄乱了Logger类实例使用的缓冲区或数据中的某些内容。此外,如果您遇到了内存不足的情况,则无法保证后续执行的代码,即使它被正确捕获。


另请注意:
多线程应用程序上下文中的日志记录系统通常不需要同步刷新。flush()的同步调用可能会改变实际应用的线程的行为,并隐藏/模糊竞争条件,这些条件将在日志记录关闭后立即出现

如果您想确保您的文本已写入日志文件,您需要使用std::endl,它会执行一次刷新,写入用于输出设备的任何缓冲区。

例如:

std::cout << "write me!n";  // no flush
std::cout << "write me!" << std::endl;  // buffer flushed