gpt4 book ai didi

c - 如果使用 lseek(),为什么文件描述符上的 read() 会失败?

转载 作者:行者123 更新时间:2023-11-30 15:05:10 30 4
gpt4 key购买 nike

在下面的示例中,我们关闭默认的 stderr 并通过 fdopen() 在临时文件上重新打开它,使用描述符 2,这是从临时文件描述符中dup()'。然后我们直接write()到这个描述符2。我们可以安全地执行此操作,因为这是对文件的第一次写入操作,因此它的缓冲区为空。之后,我们fprintf()到新的stderr。然后我们关闭stderr(因此,其关联的描述符2自动关闭)。原始描述符fd仍然有效。通过它,我们到达临时文件的开头,读取其内容并将其打印到标准输出。但输出是乱码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(void)
{
int fd;
char buf[200];
int n;
char fname[] = "/tmp/tst-perror.XXXXXX";
fd = mkstemp (fname);
fclose (stderr);
dup2 (fd, 2);
stderr = fdopen (2, "w");
fd = fileno(stderr);
char *s = "this is a test\n";
n = write(fd, s, strlen(s));
fprintf(stderr, "multibyte string\n");
fclose (stderr);
// close(fd);
// fd = open(fname, O_RDONLY);
lseek (fd, 0, SEEK_SET);
n = read (fd, buf, sizeof (buf));
printf("%.*s", (int) n, buf);
close (fd);
return 0;
}

输出为:

$ ./a.out
����

如果我们取消注释“close”和“open”行并注释“lseek”行,则输出将如预期:

$ ./a.out
this is a test
multibyte string

write()没有缓冲区,stderr在关闭时被注销,所以如果我们在读取文件之前不关闭文件,为什么输出会出现乱码?

最佳答案

不检查函数的返回值。如果它在那里,您就会发现错误。

无论如何,问题是:

  fd = fileno(stderr);     // getting the fd from current stderr
fclose (stderr); // closing stderr
...
lseek (fd, 0, SEEK_SET); // seeking on fd which was already closed

在最后一次调用和后续调用中,fd 实际上是未定义的(或者更确切地说,它引用了关闭的文件描述符)。因此,对 fd 的任何操作都将失败 EBADF(不是有效的文件描述符)。

显然,如果您再次包含 fd = open(...)fd 将变得有效并且代码将起作用。

关于c - 如果使用 lseek(),为什么文件描述符上的 read() 会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39990253/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com