Эта программа ( запускается онлайн (как C ++) здесь (кстати, кто-нибудь знает, как скомпилировать чистый 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
без окончательного \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
даже может быть небезопасным. Эти возвращаемые строки должны быть указателями на строковые литералы. (Пожалуйста, просветите меня, но я не могу вспомнить случай, когда они должны быть синтезированы во время выполнения). А строковые литералы по определению только для чтения, а доступ к данным только для чтения всегда безопасен для потоков.