OpenGroup POSIX.1-2001定义了strerror_r,Linux标准基础核心规范3.1也是如此.但我找不到对错误消息可合理预期的最大大小的引用.我希望有一些定义可以放在我的代码中,但没有我能找到的.
代码必须是线程安全的.这就是使用strerror_r而不是strerror的原因.
有人知道我可以用的符号吗?我应该创建自己的?
int result = gethostname(p_buffy, size_buffy); int errsv = errno; if (result < 0) { char buf[256]; char const * str = strerror_r(errsv, buf, 256); syslog(LOG_ERR, "gethostname failed; errno=%d(%s), buf='%s'", errsv, str, p_buffy); return errsv; }
从文件:
公开集团基本规格第6期:
错误
如果出现以下情况,strerror_r()函数可能会失败:
[ERANGE]通过strerrbuf和buflen提供的存储空间不足,无法包含生成的消息字符串.
从来源:
的glibc-2.7 /的glibc-2.7 /串/ strerror.c:41:
char * strerror (errnum) int errnum; { ... buf = malloc (1024);
小智.. 12
具有足够大的静态限制可能对所有情况都足够好.如果您确实需要获取整个错误消息,可以使用GNU版本的strerror_r,或者您可以使用标准版本并使用连续更大的缓冲区轮询它,直到您得到所需的内容.例如,您可以使用类似下面的代码.
#include#include #include #include /* Call strerror_r and get the full error message. Allocate memory for the * entire string with malloc. Return string. Caller must free string. * If malloc fails, return NULL. */ char *all_strerror(int n) { char *s; size_t size; size = 1024; s = malloc(size); if (s == NULL) return NULL; while (strerror_r(n, s, size) == -1 && errno == ERANGE) { size *= 2; s = realloc(s, size); if (s == NULL) return NULL; } return s; } int main(int argc, char **argv) { for (int i = 1; i < argc; ++i) { int n = atoi(argv[i]); char *s = all_strerror(n); printf("[%d]: %s\n", n, s); free(s); } return 0; }
Adam Rosenfi.. 9
我不担心它 - 256的缓冲区大小绰绰有余,1024是过度杀伤.如果需要存储错误字符串,则可以使用strerror()
而不是strerror_r()
,然后可选地strdup()
使用结果.但这不是线程安全的.如果你真的需要使用strerror_r()
而不是strerror()
线程安全,只需使用256的大小.在glibc-2.7
,最长的错误消息字符串是50个字符("无效或不完整的多字节或宽字符").我不希望未来的错误消息显着更长(在最坏的情况下,更长的几个字节).
具有足够大的静态限制可能对所有情况都足够好.如果您确实需要获取整个错误消息,可以使用GNU版本的strerror_r,或者您可以使用标准版本并使用连续更大的缓冲区轮询它,直到您得到所需的内容.例如,您可以使用类似下面的代码.
#include#include #include #include /* Call strerror_r and get the full error message. Allocate memory for the * entire string with malloc. Return string. Caller must free string. * If malloc fails, return NULL. */ char *all_strerror(int n) { char *s; size_t size; size = 1024; s = malloc(size); if (s == NULL) return NULL; while (strerror_r(n, s, size) == -1 && errno == ERANGE) { size *= 2; s = realloc(s, size); if (s == NULL) return NULL; } return s; } int main(int argc, char **argv) { for (int i = 1; i < argc; ++i) { int n = atoi(argv[i]); char *s = all_strerror(n); printf("[%d]: %s\n", n, s); free(s); } return 0; }
我不担心它 - 256的缓冲区大小绰绰有余,1024是过度杀伤.如果需要存储错误字符串,则可以使用strerror()
而不是strerror_r()
,然后可选地strdup()
使用结果.但这不是线程安全的.如果你真的需要使用strerror_r()
而不是strerror()
线程安全,只需使用256的大小.在glibc-2.7
,最长的错误消息字符串是50个字符("无效或不完整的多字节或宽字符").我不希望未来的错误消息显着更长(在最坏的情况下,更长的几个字节).
该程序(在此处在线运行(作为C ++)):
#include#include #include int main(){ const int limit = 5; int unknowns = 0; int maxlen = 0; int i=0; char* s = strerror(i); while(1){ if (maxlen 列出并打印系统上的所有错误,并跟踪最大长度。从外观上看,该长度不超过49个字符(纯字符,
strlen
不带final\0
),因此在留有余地的情况下,64-100应该足够了。我很好奇是否只能通过返回结构来避免整个缓冲区大小的协商,以及是否存在不返回结构的根本原因。因此,我进行了基准测试:
#define _POSIX_C_SOURCE 200112L //or else the GNU version of strerror_r gets used #include#include #include #include typedef struct { char data[64]; } error_str_t; error_str_t strerror_reent(int errn) __attribute__((const)); error_str_t strerror_reent(int errn){ error_str_t ret; strerror_r(errn, ret.data, sizeof(ret)); return ret; } int main(int argc, char** argv){ int reps = atoi(argv[1]); char buf[64]; volatile int errn = 1; for(int i=0; i 并且两者在-O2下的性能差异很小:
gcc -O2 : The VAL version is slower by about 5% g++ -O2 -x c++ : The VAL version is faster by about 1% than the standard version compiled as C++ and by about 4% faster than the standard version compiled as C (surprisingly, even the slower C++ version beats the faster C version by about 3%).无论如何,我认为
strerror
甚至允许线程不安全也很奇怪。这些返回的字符串应该是指向字符串文字的指针。(请启发我,但是我想不起来应该在运行时将它们综合的情况)。根据定义,字符串文字是只读的,对只读数据的访问始终是线程安全的。