这是我的计划。
#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
时会出现什么问题?
答案 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
的基本目的不是“我希望此缓冲区中的字符串”;它是“我想要一个以后不会被库覆盖的字符串。”