您好我是一名学生,刚开始学习低级c编程。我试图通过此程序了解read()
和write()
方法。
#include <unistd.h>
#include <stdlib.h>
main()
{
char *st;
st=calloc(sizeof(char),2);//allocate memory for 2 char
read(0,st,2);
write(1,st,2);
}
当我尝试输入超过2个输入字符时,我预计它会给出分段错误。但是当我执行程序并在输出“as”后输入“asdf”时,它会执行“df”命令。
我想知道为什么当我们为一个大小为2的字符串分配超过2个字符时它不会给出分段错误。为什么它将输入的rest(在2 char之后)作为命令执行而不是将其作为输出仅?
还阅读read()的man page我发现read()应该给出EFAULT错误,但它没有。
我正在使用linux。
答案 0 :(得分:3)
你的read
明确指出它只需要两个字符就可以了。您不将更多字符添加到st
区域,这样您就不会违反任何分段。
至于为什么它正在执行df
部分,这实际上不会发生在我的直接系统上,因为程序一直挂起,直到按下ENTER,并且看起来程序的I / O正在吸收额外的数据。但是,即时系统是Cygwin - 请参阅下面的更新,了解“真正的”UNIX机箱上的行为。
如果EFAULT
超出您的地址空间或无效,您将获得st
。情况并非如此。
更新
在Ubuntu 9上尝试这个,我看到行为与你的相同。当我提供字符asls
时,程序输出as
然后执行目录列表
这意味着你的程序只读取两个字符,剩下的就是“下一个”程序要读取,这就是shell。
请确保您不要尝试输入:
asrm -rf /
(不,严肃地说,不那样做。)
答案 1 :(得分:2)
您要求read()
读取不超过2个字符(第三个参数到read()
),因此它会覆盖您提供的缓冲区中不超过两个字符。这就是为什么没有任何错误行为的原因。
答案 2 :(得分:1)
读取()时,指定所需的字节数。除非你的libc坏了,否则你不会得到更多,所以只要你的计数永远不会超过你的缓冲区的大小,你就永远不会超出缓冲区的末尾。额外的字节保留在流中,下一个read()将获得它们。如果您的应用程序中没有下一个read(),则生成它的过程(通常是shell)可能会看到它们,因为从shell生成控制台应用程序涉及将shell的输入和输出流附加到这个过程。 shell是否看到并获取字节部分取决于libc在幕后进行了多少缓冲,以及它是否能够/“取消”退出时的任何缓冲字节。
答案 3 :(得分:0)
with read(0,st,2);你从标准输入读取2个字符。 你键入的其他内容将不会被程序所控制,但不会被省略,因此击键将返回到程序启动的shell(df并输入)。
答案 4 :(得分:0)
由于你只读了2个字符,所以没有问题。 df字符不会被你的程序占用,因此它们会留在终端缓冲区中,并由shell使用:
asdf\n
as
并将df\n
留在tty缓冲区df\n
并执行df命令。有趣的事情:
strace -e read, write ./yourprogram
read(0, st, 5)