从 C 中的 fstream 获取有意义的错误消息;

发布于 2024-08-29 06:02:14 字数 433 浏览 11 评论 0原文

以可移植的方式从 std::fstreams 获取有意义的文件访问错误消息的最佳方法是什么? badbitsfailbits 的原始性变得有点烦人。我之前已经针对 win32 和 POSIX 编写了自己的异常层次结构,这比 STL 的方式灵活得多。

我从 fstream 的向下转型 catch (std::exception) 的 what 方法中收到“basic::ios_clear”作为错误消息> 启用了例外。这对我来说意义不大,尽管我确实知道问题是什么,但我希望我的程序能够提供更多信息,这样当我几个月后开始部署时,我的生活会更轻松。

Boost 中是否有任何东西可以从 fstream 的跨平台和跨 STL 实现的实现中提取有意义的消息?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

高跟鞋的旋律 2024-09-05 06:02:14

没有人阻止您检查errno/strerror(例如在异常处理程序中)以获取更具体的失败原因。

更新——关于可移植性

顺便说一句,IIRC Visual Studio 的 fstream 实现调用 _open/_read/_write/etc。 CRT 方法,设置errnoMicrosoft 不保证 CRT 方法返回后 GetLastError 仍包含正确的值。同上,cygwin、mingw 等实现设置了 errno,但没有关于 GetLastError 的声明或保证。

因此,我坚持我的主张,即您需要、可以并且因此想要做的就是检查errno

现在,考虑到上述所有内容,如果您仍然想通过使用 Boost::System 而不是简单地调用 strerror 来使您的生活复杂化并过度设计,那么我猜我的定义和您的优雅和简洁的定义并不相同。 :)

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. :)

失眠症患者 2024-09-05 06:02:14

您想要什么信息? badbit 表示 I/O 错误。 eofbit表示eof。 failbit 表示解析错误。

无论如何,为了消除一种解决方案,我认为您不能因为 ADL 而覆盖本机类型输入函数。您可以实现 operator>>(istream, input_safe_int),其中 input_safe_int 是由 int& 构造的。在里面放一个 try 块,等等。

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.

初吻给了烟 2024-09-05 06:02:14

我很幸运地捕获了 std::ios_base::failure< /code>,然后重新引发 std::system_error 使用 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 };
  }
}

这适用于 UNIX 和 Windows,因为“所有 errno 值都是...UNIX 兼容的”()。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文