这个程序(在这里在线运行(作为 C++)):
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(){
const int limit = 5;
int unknowns = 0;
int maxlen = 0;
int i=0; char* s = strerror(i);
while(1){
if (maxlen<strlen(s)) maxlen = strlen(s);
if (/*BEGINS WITH "Unknown "*/ 0==strncmp("Unknown ", s , sizeof("Unknown ")-1) )
unknowns++;
printf("%.3d\t%s\n", i, s);
i++; s=strerror(i);
if ( limit == unknowns ) break;
}
printf("Max: %d\n", maxlen);
return 0;
}
列出并打印系统上的所有错误并跟踪最大长度。从外观上看,长度不超过49 个字符(纯strlen
's 没有最后的\0
),所以有一些余地,64-100 应该绰绰有余。
我很好奇是否不能简单地通过返回结构来避免整个缓冲区大小协商,以及是否存在不返回结构的根本原因。所以我进行了基准测试:
#define _POSIX_C_SOURCE 200112L //or else the GNU version of strerror_r gets used
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
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<reps; i++){
#ifdef VAL
error_str_t err = strerror_reent(errn);
#else
strerror_r(errn, buf, 64);
#endif
}
return 0;
}
并且两者在 -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
甚至允许线程不安全是非常奇怪的。那些返回的字符串应该是指向字符串文字的指针。(请赐教,但我想不出应该在运行时合成它们的情况)。并且字符串文字根据定义是只读的,并且对只读数据的访问始终是线程安全的。