代码之家  ›  专栏  ›  技术社区  ›  mat_geek

我应该给你多大的尺寸?

  •  27
  • mat_geek  · 技术社区  · 17 年前

    strerror_r 也一样 The Linux Standard Base Core Specification 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期:

    错误

    • [伊兰奇] 通过strerrbuf和buflen向 包含生成的消息字符串。

    来源:

        char *
        strerror (errnum)
             int errnum;
        {
            ...
            buf = malloc (1024);
    
    3 回复  |  直到 17 年前
        1
  •  13
  •   user25148 user25148    14 年前

    有足够大的静态极限可能对所有情况都足够好。 如果确实需要获取整个错误消息,可以使用 GNU version of strerror_r 也可以使用标准版本 然后用连续更大的缓冲区进行轮询,直到得到所需的结果。例如, 您可以使用下面的代码。

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* 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;
    }
    
        2
  •  10
  •   Adam Rosenfield    17 年前

    我不担心这个问题——256的缓冲区大小远远不够,1024个缓冲区太过了。你可以利用 strerror() 而不是 strerror_r() strdup() 如果需要存储错误字符串,则返回结果。不过,这不是线程安全的。如果你真的需要 斯特雷罗() 而不是 为了线程安全,只需使用256的大小。在 glibc-2.7

        3
  •  5
  •   Petr Skocik    6 年前

    这个节目( run online (as C++) here ):

    #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 )所以,有一些余地,64100应该足够了。

    #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;
    }
    

    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 甚至允许线程不安全。返回的字符串应该是指向字符串文本的指针。(请启发我,但我想不出应该在运行时合成它们的情况)。字符串文本按定义是只读的,对只读数据的访问始终是线程安全的。