为什么 strerror_r 在使用 gnu90 和 c90 标准编译时表现不同?
Why does strerror_r behave differently when compiled with gnu90 and c90 standards?
这是我的程序。
#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
时出了什么问题?
对于 -std=c89
,您要求实现专门提供 ISO 9899:1989 标识符部分的声明。标识符 strerror_r
不是 C89(或 C99)的一部分,因此没有原型。因此,您会收到有关隐式声明的警告。
如果您查看相关的 header,您可能会发现 strerror_r 原型被掩埋在 #ifdef
的迷宫中。 -std
选项更改影响原型可见性的 pre-defined 宏集。
strerror_r(3) 说:
The XSI-compliant strerror_r() is preferred for portable applications. It returns the error string in the user-supplied buffer buf of length buflen.
The GNU-specific strerror_r() returns a pointer to a string containing the error message. This may be either a pointer to a string that the function stores in buf, or a pointer to some (immutable) static string (in which case buf is unused). If the function stores a string in buf, then at most buflen bytes are stored (the string may be truncated if buflen is too small and errnum is unknown). The string always includes a terminating null byte.
所以这不仅仅是声明是否可见的问题(这本身就是一个相当大的问题 - 当您收到“隐式声明”警告时,您根本不应该期望该程序能够运行.) 这也是您调用的函数版本的问题。 GNU 版本有时 returns 指向库中常量字符串的指针,而不是将字符串复制到调用者提供的缓冲区。
strerror_r
的基本目的不是“我想要这个缓冲区中的字符串”;它是“我想要一个以后不会被库覆盖的字符串。”
这是我的程序。
#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
时出了什么问题?
对于 -std=c89
,您要求实现专门提供 ISO 9899:1989 标识符部分的声明。标识符 strerror_r
不是 C89(或 C99)的一部分,因此没有原型。因此,您会收到有关隐式声明的警告。
如果您查看相关的 header,您可能会发现 strerror_r 原型被掩埋在 #ifdef
的迷宫中。 -std
选项更改影响原型可见性的 pre-defined 宏集。
strerror_r(3) 说:
The XSI-compliant strerror_r() is preferred for portable applications. It returns the error string in the user-supplied buffer buf of length buflen.
The GNU-specific strerror_r() returns a pointer to a string containing the error message. This may be either a pointer to a string that the function stores in buf, or a pointer to some (immutable) static string (in which case buf is unused). If the function stores a string in buf, then at most buflen bytes are stored (the string may be truncated if buflen is too small and errnum is unknown). The string always includes a terminating null byte.
所以这不仅仅是声明是否可见的问题(这本身就是一个相当大的问题 - 当您收到“隐式声明”警告时,您根本不应该期望该程序能够运行.) 这也是您调用的函数版本的问题。 GNU 版本有时 returns 指向库中常量字符串的指针,而不是将字符串复制到调用者提供的缓冲区。
strerror_r
的基本目的不是“我想要这个缓冲区中的字符串”;它是“我想要一个以后不会被库覆盖的字符串。”