当我在测试期间手动设置errno时,strerror_r返回垃圾

Rob*_*nes 4 c++ error-handling ubuntu unit-testing mocking

在测试期间,我有一个模拟对象设置errno = ETIMEDOUT; 我正在测试的对象看到错误并调用strerror_r来获取错误字符串:

if (ret) {
    if (ret == EAI_SYSTEM) {
        char err[128];
        strerror_r(errno, err, 128);
        err_string.assign(err);
    } else {
        err_string.assign(gai_strerror(ret));
    }
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么strerror_r要回垃圾.我甚至试过打电话

strerror_r(ETIMEDOUT, err, 128)
Run Code Online (Sandbox Code Playgroud)

直接,仍然有垃圾.我肯定错过了什么.看来我得到的函数的gnu版本不是posix版本,但在这种情况下不应该有任何区别.

编辑

我在Ubuntu 8.04上.glibc版本在features.h中看起来像2.7.

Mic*_*urr 10

根据这个页面http://linux.die.net/man/3/strerror_r,如果您使用的是GNU版本strerror_r(),该函数可能会决定不将任何内容存储到您提供的缓冲区中; 你需要使用从函数返回的字符串(看起来像一个相当奇怪的界面):

GNU特定的strerror_r()返回指向包含错误消息的字符串的指针.这可以是指向函数存储在buf中的字符串的指针,也可以是指向某个(不可变的)静态字符串的指针(在这种情况下,buf未使用).如果函数在buf中存储字符串,则最多存储buflen字节(如果buflen太小,则字符串可能被截断)并且字符串总是包括终止空字节.

因此,如果你碰巧使用GNU版本,你不能依赖你的err缓冲区来放入任何有用的东西,除非strerror_r()返回地址err.

  • 那我怎么得到xsi/posix版本? (2认同)

Unk*_*own 5

问题是 Linux 有两个 strerror_r 函数。如果您阅读了手册,

   int strerror_r(int errnum, char *buf, size_t buflen);
               /* XSI-compliant */

   char *strerror_r(int errnum, char *buf, size_t buflen);
               /* GNU-specific */


The XSI-compliant version of strerror_r() is provided if:
       (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
Run Code Online (Sandbox Code Playgroud)

g++ 编译器自动定义 _GNU_SOURCE,因此您使用的是该函数的 GNU 版本,该函数不一定在您提供的缓冲区中存储消息。