作者热门文章
- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在使用 strerror_r在日志记录辅助函数中。如手册页所述,此函数有两个版本。 POSIX 版本返回一个 int。 GNU 版本返回一个字符串 (char*)。
因此,为了让我的 C++ 代码更具可移植性,我有一段与此类似的代码:
char buffer[1000];
int size = 1000;
int result = 0;
char* msg = buffer;
buffer[0] = '\0';
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
#else
result = strerror_r(err, buffer, size);
if (result != 0)
{
sprintf(buffer, "unknown error: %d", err);
}
#endif
LogToFile(msg);
在上面的代码块中,它将根据 _GNU_SOURCE
的存在使用任一版本的 strerror_r
,它总是由 g++ 设置,因为 libstdc++ 需要它。在 Mac 和 Unix 的其他变体上,它将使用 POSIX 版本。
现在这段代码在很长一段时间内一直运行良好,直到今天。试图在 Alpine Linux 上编译我的代码的用户今天在使用 strerror_r
main.cpp:16:21 error: invalid conversion from 'int' to 'char*' [-fpermissive]
映射到这一行:
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
在这个平台上的 /usr/include/string.h
处达到顶峰揭示了以下内容:
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
|| defined(_BSD_SOURCE)
...
int strerror_r (int, char *, size_t);
...
#endif
看来无论使用什么编译环境,strerror_r 的唯一声明版本是返回 int 的 POSIX 版本。这样就解释了为什么会发生错误。
在不必告诉用户他们可以手动#undef _GNU_SOURCE
或修改源代码的情况下,我该如何解决这个问题,以便代码可以继续移植?全局取消定义 _GNU_SOURCE 可能是行不通的,因为这是 C++(并且如上所述,libstdc++ 需要)。我正在尝试查看是否还有其他可以测试的宏组合,但我无法得出任何明显的结论。
最佳答案
您可以利用 C++ 函数重载:
char* check_error(int result, char* buffer, int err) {
if(result)
sprintf(buffer, "unknown error: %d", err);
return buffer;
}
char* check_error(char* result, char*, int) {
return result;
}
并且在使用中去掉条件编译:
char buffer[1000];
buffer[0] = '\0';
char* msg = check_error(strerror_r(err, buffer, sizeof buffer), buffer, err);
LogToFile(msg);
关于c++ - 在 Alpine Linux 上错误地声明了 strerror_r,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41953104/
我是一名优秀的程序员,十分优秀!