作者在标题A bus error on my platform
下介绍了this code
#include <fstream>
#include <iostream>
int main()
{
std::ofstream log("oops.log");
std::cout.rdbuf(log.rdbuf());
std::cout << "Oops!\n";
return 0;
}
字符串“Oops!\n”被打印到文件“oops.log”。代码不会恢复cout的streambuf,但VS2010没有报告运行时错误。
4条答案
按热度按时间cpjpxq1n1#
由于
log
和std::cout
共享一个缓冲区,因此该缓冲区可能会被释放两次(一次是在log
超出作用域时,另一次是在程序终止时)。这会导致未定义的行为,所以很难确切地解释为什么它在他的机器上触发了总线错误,而在你的机器上却默默地失败了。
tv6aics12#
由于其他答案没有提到该怎么做,我将在这里提供。您需要保存和恢复cout应该管理的缓冲区。例如:
现在当
cout
的缓冲区在cout
在程序结束时被销毁之前被替换时,所以当cout
销毁它的缓冲区时,正确的事情发生了。对于简单地重定向标准io,通常环境已经有能力为你做这件事(例如,shell中的io重定向)。而不是上面的代码,我可能只是运行程序:
还有一件事要记住的是,
std::cout
是一个全局变量,与其他全局变量有着相同的缺点。与其修改它,甚至使用它,你可能更喜欢使用常规技术来避免全局变量。例如,你可以传递一个std::ostream &log_output
参数,并使用它,而不是让代码直接使用cout
。lstz6jyr3#
您的程序具有未定义的行为。
全局
cout
对象的析构函数将在超出作用域时删除流缓冲区,log
也是如此,它也拥有相同的流缓冲区。因此,您将删除相同的对象两次。当一个程序有未定义的行为,任何事情都可能发生,从格式化你的硬盘驱动器终止没有任何错误。
例如,在我的平台上,程序从
main()
返回后进入无限循环。1szpjjfi4#
好吧,我在我的应用程序的某些特定版本上收到了SEGMENTATION FAULT。应用程序在其中一个设备上运行正常,但当为另一个架构构建时:
我花了两天时间想弄清楚到底出了什么问题。