【发布时间】:2017-02-18 10:14:26
【问题描述】:
The standard 说:
perror() 函数不应改变标准错误流的方向。
This 是perror() 在 GNU libc 中的实现。
以下是在调用perror() 之前,stderr 面向宽、面向多字节和不面向时的测试。
测试 1) 和 2) 均正常。问题在于测试 3)。
1) stderr 面向广泛:
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
int main(void)
{
fwide(stderr, 1);
errno = EINVAL;
perror("");
int x = fwide(stderr, 0);
printf("fwide: %d\n",x);
return 0;
}
$ ./a.out
Invalid argument
fwide: 1
$ ./a.out 2>/dev/null
fwide: 1
2) stderr 是面向多字节的:
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
int main(void)
{
fwide(stderr, -1);
errno = EINVAL;
perror("");
int x = fwide(stderr, 0);
printf("fwide: %d\n",x);
return 0;
}
$ ./a.out
Invalid argument
fwide: -1
$ ./a.out 2>/dev/null
fwide: -1
3) stderr 没有方向性:
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
int main(void)
{
printf("initial fwide: %d\n", fwide(stderr, 0));
errno = EINVAL;
perror("");
int x = fwide(stderr, 0);
printf("fwide: %d\n", x);
return 0;
}
$ ./a.out
initial fwide: 0
Invalid argument
fwide: 0
$ ./a.out 2>/dev/null
initial fwide: 0
fwide: -1
如果perror() 被重定向,为什么它会改变流的方向?这是正确的行为吗?
this 代码如何工作?这个__dup 的诡计是什么?
【问题讨论】:
-
您是否考虑过在第一个示例中检查对
fwide()的初始调用?成功了吗?你怎么知道的? -
@RastaJedi 上面说的是宽字符函数和多字节函数,比如
fprintf(stderr, "something");vs.fwprintf(stderr,L"something");,但是这个例子使用了shell重定向,这是另一回事。 -
@JonathanLeffler 在示例 3 中调用
perror()之前调用fwide(stderr,0);)返回0,正如预期的那样,因为尚未对stderr执行任何操作。请参阅编辑后的示例 3) - 测试表明一切都是正确的。 -
@RastaJedi 请参阅编辑后的示例 3) - 测试表明一切正常,因此问题不在 shell 中。
-
我问的是第一个例子,而不是第三个。但是,
fwide()的 POSIX 规范提到很难发现错误,并建议在调用函数之前设置errno = 0。但是,在我看来,示例 3 的非重定向变体是有问题的变体。perror()写入stderr流,因此一旦perror()返回,它应该被赋予一个方向,但它似乎没有发生。重定向 stderr 时的变化是我所期望的行为。
标签: file-io io posix wchar-t widechar