为什么使用gnu90和c90标准编译时strerror_r的行为会有所不同?

时间:2015-12-15 14:22:59

标签: c gcc gnu c89

这是我的计划。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int main()
{
        char errbuf[256];

        errno = 0;
        strtoul("99999999999999999999999999999999999999999999", NULL, 0);
        strerror_r(errno, errbuf, sizeof errbuf);
        printf("strerror_r: %s\n", errbuf);

    return 0;
}

当我使用-std=gnu90-std=gnu99进行编译时,我得到了预期的输出。

susam@nifty:~/lab/linux$ rm -f a.out && gcc -std=gnu90 -Wall -Wextra -pedantic foo.c && ./a.out 
strerror_r: Numerical result out of range
susam@nifty:~/lab/linux$ rm -f a.out && gcc -std=gnu99 -Wall -Wextra -pedantic foo.c && ./a.out 
strerror_r: Numerical result out of range

但是当我使用-std=c90-std=c99进行编译时,我收到了警告,但我没有看到strerror_r将字符串放入errbuf

lone@debian:~/lab/linux$ rm -f a.out && gcc -std=c90 -Wall -Wextra -pedantic foo.c && ./a.out
foo.c: In function ‘main’:
foo.c:12:2: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
  strerror_r(errno, errbuf, sizeof errbuf);
  ^
strerror_r:
lone@debian:~/lab/linux$ rm -f a.out && gcc -std=c99 -Wall -Wextra -pedantic foo.c && ./a.out
foo.c: In function ‘main’:
foo.c:12:2: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
  strerror_r(errno, errbuf, sizeof errbuf);
  ^
strerror_r:

使用-std=c90-std=c99时会出现什么问题?

2 个答案:

答案 0 :(得分:5)

使用$ kill -TERM <some_pid> ,您要求实现专门提供ISO 9899:1989标识符部分的声明。标识符-std=c89不是C89(或C99)的一部分,因此没有原型。因此,您会收到有关隐式声明的警告。

如果查看相关标题,您可能会发现埋在strerror_r s迷宫中的strerror_r原型。 #ifdef选项更改了影响原型可见性的预定义宏集。

答案 1 :(得分:1)

strerror_r (3)说:

  

符合XSI标准的strerror_r()是便携式应用程序的首选。它返回用户提供的长度为buflen的缓冲区buf中的错误字符串。

     

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

因此,这不仅仅取决于声明是否可见(这本身就是一个非常大的问题 - 当你收到“隐式声明”警告时,你不应该期望程序能够正常工作。)这也是你要调用的函数版本的问题。 GNU版本有时会返回一个指向库中常量字符串的指针,而不是将字符串复制到调用者提供的缓冲区。

strerror_r的基本目的不是“我希望此缓冲区中的字符串”;它是“我想要一个以后不会被库覆盖的字符串。”