开发者

Getting meaningful error messages from fstream's in C++

What is the best way to get meaningful file access error messages, in a portable way from std::fstreams ? The primitiveness of badbits and failbits is getting to be bit annoying. I have written my own exception hierarchies against win32 and POSIX before, and that was far more flexible than the way the STL does it.

I am getting "basic::ios_clear" as an error message from the what method of a downcasted catch (std::exception) of a fstream which has exceptions enabled. This doesn't mean much to me, although I do know what the problem is I'd like my program to be a tad more informative so that when I start deployment a few months later my life will be easier.

Is there anything in Boost to extract meaningful messages out of the fstream'开发者_运维问答s implementation cross platform and cross STL implementation ?


Nobody stops you from also checking errno/strerror (e.g. in your exception handler) for a more specific reason for failure.

UPDATE -- regarding portability

Incidentally, IIRC Visual Studio's fstream implementation calls the _open/_read/_write/etc. CRT methods, which set errno. Microsoft makes no guarantee about GetLastError still containing the correct value after the CRT methods return. Idem for the cygwin, mingw etc. implementations, which set errno with no claims or guarantees about GetLastError.

So I stand by my claim that all you need, can, and therefore want to do is check errno.

Now, given all of the above, if you still want to complicate your life and overengineer by using Boost::System instead of simply calling strerror then I guess my definition and your definition of elegance and simplicity are not the same. :)


What information do you want? badbit indicates an I/O error. eofbit indicates eof. failbit indicates a parse error.

To eliminate one solution, anyway, I don't think you can override the native-type input functions because of ADL. You could implement operator>>(istream, input_safe_int) where input_safe_int is constructed from int&. Put a try block inside, etc.


I've had luck catching the std::ios_base::failure and then re-raising a std::system_error using errno:

terminate called after throwing an instance of 'std::system_error'
  what():  broken/path: No such file or directory
#include <fstream>

int main() {
  const std::string filename{ "broken/path" };
  try {
    std::ifstream file{ filename };
    file.exceptions(std::ios::failbit); // std::ios_base_failure is thrown here
  } catch (std::ios_base::failure&) {
    throw std::system_error{ errno, std::generic_category(), filename };
  }
}

This works on UNIX and Windows because "All errno values are … UNIX-compatible" (source).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜