2016-04-28 1 views
1

Извините за странный заголовок. Ограничено до 150 символов, поэтому нельзя использовать правильные предложения.В C++ std :: streams, после сбоя, как получить причину сбоя? Обязательно: threadsafe и общий для Windows и Linux (или, по крайней мере, Msvc/Gcc)

Так скажем, я сделал следующее, чтобы узнать, что что-то пошло не так с моим потоком файла:

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/# определить/и т.д.: Тьфу, но может быть единственным выбором

я сделал некоторые поиски, но я не найти «это, безусловно, работать в разумный еще немного от платформы зависимый путь "ответ ... Тем не менее, я чувствую, что это« очевидно, дублирующий вопрос », но я не могу найти оригинал ...

+0

Вы можете сделать поток бросить по ошибке, если хотите. – Holt

+1

Ближайший, который вы можете получить в C++, это ['std :: io_errc'] (http://en.cppreference.com/w/cpp/io/io_errc) –

+4

[" '// потоки не выбрасывают ошибку, потому что C++ '"] (http://en.cppreference.com/w/cpp/io/basic_ios/exceptions). Не то, чтобы это гарантировало наличие полезного 'what()'. – BoBTFish

ответ

2

Вы всегда можете бросить свои собственные исключения, используя 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.

+0

Я думаю, std :: system_error может быть тем, что я искал! Я попробую это, а затем пометьте это как ответ, если он удовлетворит мои требования. – JamEnergy

+0

Я отредактировал в фрагменте для получения сообщения об ошибке, не переходя через исключение, так как одна из моих основных проблем заключалась в получении прочитанного сообщения (вместо исключения исключений, хотя это также полезно). – JamEnergy

0

Это лучшее, что я мог придумать. Это ответ «yuck», но по крайней мере вы можете поместить «yuck» в одну функцию и спрятать ее в каком-нибудь файле cpp. std :: ios также увеличивает потоки потоков.

Требуется #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" 
} 
Смежные вопросы