【发布时间】:2021-04-15 20:36:24
【问题描述】:
下面的代码返回 EFAULT (errno == 14)。我会很感激帮助找出原因。
我也尝试使用 select() 来实现代码,但仍然得到相同的错误代码。
我在 Python 上运行了非常相似的代码,没有任何问题。
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
int read_fail1(int fd)
{
int n;
char buf[500];
for (;;)
{
buf[strlen(buf)-1] = 0;
n = read(fd, buf, strlen(buf)-1);
if (n == -1)
{
if (errno == EFAULT)
{
fprintf(stderr, "EFAULT");
return 42;
}
}
else if (n > 0)
{
fprintf(stderr, "%s", buf);
}
}
}
int main(int argc, const char *argv[])
{
const char *myfifo = "pipeMUD";
mkfifo(myfifo, 0666);
int fd = open(myfifo, O_RDWR | O_NONBLOCK);
if (fd <= 0)
return 42;
read_fail1(fd);
return 0;
}
发布答案编辑:
正如下面链接的帖子中提到的,如果将无效地址传递给内核,则会抛出 EFAULT。我猜在 Linux 上,根据上面的代码,给 read() 传递一个长度为 0 的 count 参数也会导致 EFAULT 被返回。
【问题讨论】:
-
buf[strlen(buf)-1] = 0;这是未定义的行为,因为buf在运行时还不包含有效的字符串。 -
????不敢相信我没有看到。对不起。尴尬
-
贴出的代码编译不干净!例如,
int main(int argc, const char *argv[])会导致两条关于未使用参数的警告消息。 (建议使用:int main( void )。编译时,始终启用警告,然后修复这些警告。(对于gcc,至少使用:-Wall -Wextra -Wconversion -pendantic -std=gnu11)注意:其他编译器使用不同的选项来产生相同的结果。 -
关于:
n = read(fd, buf, strlen(buf)-1);函数:read()返回ssize_t而不是int -
关于:
int fd = open(myfifo, O_RDWR | O_NONBLOCK);因为发布的代码只是从 FIFO 读取,应该只打开读取,而不是写入
标签: c linux named-pipes nonblocking