提问人:JamEnergy 提问时间:4/28/2016 最后编辑:JamEnergy 更新时间:10/26/2019 访问量:605
在C++ std::流中,失败后,如何获取失败原因?必需:线程安全,对 Windows 和 Linux 通用(或至少 Msvc/Gcc)
In C++ std:: streams, after a failure, how to get a failure reason? Required: threadsafe and common to Windows and Linux (or at least Msvc/Gcc)
问:
对不起,标题很奇怪。限制为 150 个字符,因此无法使用正确的句子。
因此,假设我做了以下操作来发现我的文件流出了问题:
std::ofstream ofs;
do_stuff_with(ofs);
// streams don't throw on error because C++ [edit: we can make them do so, but the .what()s aren't very user-friendly]
// so we have to check for failure manually
if(!ofs){
auto fail_code = errno; // threadsafe on Win/Linux
// but what goes here?
}
1) strerror: 非线程安全
2) strerror_s:不在海湾合作委员会?或者是吗?
3) strerror_r:不在 Msvc 中?或者是吗?
4)#ifdef/#define/等:哎呀,但可能是唯一的选择
我确实做了一些搜索,但我没有找到“这肯定会以一种明智但略微依赖平台的方式工作”的答案......也就是说,我觉得这“显然是一个重复的问题”,但我找不到原文......
答:
这是我能想到的最好的。这是“yuck”的答案,但至少你可以把“yuck”放在一个函数中,并将其隐藏在某个cpp文件中。当然,std::ios 也涵盖了 boost 流。
需要 #ifdefs 所以这是一个作弊。我相信 Visual Studio 默认 #defines _WIN32,所以至少你不必设置该基础结构本身。
void check_stream(std::ios & stream)
{
if (!stream){
char err[1024] = { 0 };
#ifdef _WIN32
strerror_s(err, errno);
#else
strerror_r(errno, err, 1024);
#endif
throw MyException(err);
}
}
我自己的解决方案让我很难过,所以希望会有更好的解决方案。但时间是有限的,所以只要屈服于黑暗面,使用这样的东西,然后继续你的生活。:P
try{
boost::filesystem::ifstream ifs("testfile");
check_stream(ifs);
}
catch (std::exception & e){
std::cout << e.what(); // "No such file or directory"
}
您始终可以使用以下命令引发自己的异常:std::system_error
#include <cerrno>
#include <fstream>
#include <iostream>
#include <system_error>
int main()
{
try
{
std::ofstream foo{"/root/bar.baz"};
foo << "bla" << std::endl;
foo.close();
if(!foo)
throw std::system_error{errno, std::generic_category()};
}
catch(const std::system_error& err)
{
std::cout << "Error: " << err.code() << " - " << err.what() << std::endl;
}
return 0;
}
这将返回 .Error: generic:13 - Permission denied
评论
从 C++ 11 开始,您可以使用该类:std::error_code
std::cout << std::error_code{errno, std::generic_category()}.message();
事实上,你甚至可以做得比这更短一点:
std::cout << std::generic_category().message(errno);
虽然我必须说,我发现第一个更惯用。
顺便说一句,还有 ,它似乎在很大程度上等同于 Unix,但在 Windows 上,它可以用来翻译 Windows API 错误代码,例如返回者等。std::system_category()
generic_category()
GetLastError()
这与异常中使用的类相同,但如果只想获取错误消息,则无需创建异常实例。std::system_error
评论
std::io_errc
// 流不会因为 C++ 而引发错误
”。并不是说它保证有一个有用的.what()
throw
what()
try
catch