1

我在这样的代码中为线程安全的 strerror_r 提供了一个 c++ 包装器:

struct MyErrno {};
std::ostream& operator<<(std::stream& os, const MyErrno& err)
{
    const int len = 128
    char buf [len];
    os << strerror_r(errno, buf, len);
    return os;
}

这只是一个简单的包装器,所以在 C++ 代码中我可以说类似

<< MyErrno() << ..

并使用 errno 的线程安全打印。使用 128 似乎也可以,因为手册页说strerror_r将返回一个指向不可变静态字符串的指针(可能是空终止),或者buf在用空终止符填充它之后返回一个指针,无论大小如何......只是不确定如果这个简单的包装器有问题(可能有问题)

4

1 回答 1

3

我不了解您要在其中使用它的完整上下文(特别是 struct 的作用是MyErrno什么,以及什么是StreamErrno,因为您的operator<<定义适用于sockaddr_in未使用的类型值)。

但是,总的来说,这不是一种安全的使用方式errno,尽管它是一种完全安全的使用方式strerror_r

问题是您很可能在这样的上下文中使用它:

if ((something) != OK) {
  std::cerr << "Something bad happened: "
            << (some value which causes your function to be called)
            << ...
}

也就是说,在失败的系统调用之间可能会有一些系统调用(输出字符串“发生了一些事情”),在 中留下一个值errno,并errno在您的函数中使用。任何系统调用都可以导致errno设置,即使错误是无害的;因此,最佳实践是errno 立即获取 的值。这将是使用自定义类型的一个很好的理由,例如MyError

struct MyError {
  int error;
  MyError(int err) : error(err) {}
};

std::ostream& operator<<(std::ostream& os, const MyError& e) {
  // as with your function, but using `e.error` instead of `errno`
}

if ((something) != OK) {
  MyError e(errno);
  std::cerr << "Something bad happened: " << e
            << ...
}
于 2013-02-21T18:23:31.803 回答