为什么使用 freopen() 和 stderr 重定向assert() 的输出可以工作,但正常重定向 std::cerr 的缓冲区则不行?

问题描述 投票:0回答:1

我想重定向

assert()
在断言失败时创建的输出,以便将其写入日志文件而不是输出窗口。我假设
assert()
使用
std::cerr
来输出,但是当将
std::cerr
重定向到我的日志文件时,
assert()
仍然输出到输出窗口而不是我的文件:

std::ofstream ofs("log-file.txt");
std::cerr.rdbuf(ofs.rdbuf());

assert(false); // Still outputs "Assertion failed: false" to the output window and not to the log file

我发现了一个具有类似问题的SO问题,其答案建议使用

freopen
代替,如下所示:

freopen("log-file.txt", "w", stderr);

这给了我一个错误:

'freopen': This function or variable may be unsafe. Consider using freopen_s instead.

freopen_s
似乎采用与
freopen
不同的参数,我无法让它工作。

另一个SO答案建议使用

freopen
,但只需将
_CRT_SECURE_NO_WARNINGS
添加到Visual Studio项目属性中的命令行即可。这确实消除了错误,并且
assert()
现在可以正确输出到我的日志文件。

但这一切似乎不必要地复杂。感觉应该有一种顺利的方法来实现我想做的事情,而不抑制 3 级编译器警告。为什么我不能简单地正常重定向

assert()
用于输出的缓冲区?如果不是 assert()
std::cout
std::cerr
,那么
 
std::clog
到底用来输出什么? (我尝试过重定向所有三个)

c++ assert cout assertion freopen
1个回答
0
投票

你的进程有一个名为

stderr
的操作系统缓冲区,这是
assert
打印到的地方,另一方面
std::cerr
是一个 C++ 对象,它打印被推入 std::cerrstderr
 的文本缓冲液。

修改

std::cerr

对象将更改
std:cerr
将打印到的缓冲区,但不会修改底层操作系统
stderr
缓冲区,其中
assert
直接打印,为了修改您需要特定于操作系统的功能,例如
freopen
dup2
(其实现由操作系统定义)

© www.soinside.com 2019 - 2024. All rights reserved.