C++ 在C++;std::streams,在发生故障后,如何获取故障原因?必需:线程安全,Windows和Linux通用(或至少Msvc/Gcc)

C++ 在C++;std::streams,在发生故障后,如何获取故障原因?必需:线程安全,Windows和Linux通用(或至少Msvc/Gcc),c++,c++11,error-handling,stream,iostream,C++,C++11,Error Handling,Stream,Iostream,很抱歉这个奇怪的标题。限制为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

很抱歉这个奇怪的标题。限制为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) 斯特雷罗:不在GCC?还是这样

3) 斯特雷罗:不在Msvc?还是这样

4) #ifdef/#define/etc:很恶心,但可能是唯一的选择


我确实做了一些搜索,但我没有找到一个“这肯定会以一种合理但稍微依赖于平台的方式工作”的答案。。。也就是说,我觉得这“显然是一个重复的问题”,但我找不到原始的…

这是我能想到的最好的问题。这是“恶心”的答案,但至少你可以把“恶心”放在一个函数中,然后把它隐藏在某个cpp文件的某个地方。当然,ios也包括boost流

需要#ifdef所以这是个骗局。我相信visualstudio默认定义了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"
}
试试看{
boost::filesystem::ifstream ifs(“testfile”);
检查流(ifs);
}
捕获(标准::异常&e){

std::cout您总是可以使用
std::system\u 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;
}
#包括
#包括
#包括
#包括
int main()
{
尝试
{
std::of stream foo{“/root/bar.baz”};

foo自C++11以来,您可以使用类
std::error\u code
来实现:

std::cout << std::error_code{errno, std::generic_category()}.message();

<代码> STD::CUT如果你想,可以让流丢到错误。C++中最接近的是。它不是保证有一个有用的<代码>()(<)/代码>。我知道异常()。但是出于某种原因,我也认为它没有被正确地实现。但是它似乎起作用,只是它给出了类似的消息。“ios_base::failbit set”而不是“没有这样的文件或目录”。正如stackoverflow上的其他地方所发现的那样,签出
抛出
什么()
try
catch
。我想std::system\u错误可能就是我一直在寻找的!我会尝试这个,然后如果结果满足我的要求,我会将它标记为答案。我编辑了一个代码片段,以便在不通过异常的情况下获取错误消息,因为我的主要问题之一是获取一条可读的消息ut(而不是抛出异常,尽管这也很有用)。
std::cout << std::generic_category().message(errno);