给定以下程序:
#include <stdio.h>
int main()
{
char buf[1024];
scanf("%s", buf);
printf("----> %s", buf);
return 0;
}
其执行如下:
grep ....| a.out
或
echo ....| a.out
我收到一个Segmentation fault
错误。有人能解释一下原因吗?
无论您要回显或重传的内容都必须包含1023个以上的字符。(1024-1表示空终止符。)
不要使用scanf
,而是使用fgets
并指定大小。或者,使用scanf
,但指定字段长度。你可以做scanf("%1023s", buf);
。如果有更多的字节可用,你总是可以再次读取其余的字节
考虑到您的测试输入,您不应该收到segfault。我只是在当地试了一下,效果很好。如果您在Linux上,由于您编写的是a.out
而不是./a.out
,根据路径的配置方式,您可能运行了错误的程序(bin文件夹中的某种a.out
?)
永远不要将scanf
与无界字符串一起使用。fgets
提供了一个更安全的替代方案,特别是如果您提供了像本答案中那样的智能包装器函数。
我假设这只是这里的示例代码,但如果不是,您可以使用实现相同的效果
WhateverYourCommandIs | sed 's/^/----> '
而不必编写自己的工具来完成这项工作。事实上,使用sed
、awk
等,您可能永远不需要自己编写文本处理工具。
来自scanf-man:
s匹配非空白字符序列;下一个指针必须是指向字符数组的指针,该数组的长度足以容纳输入序列和自动添加的终止null字符("\0")。输入字符串停止在空白处或最大字段宽度处,以先出现的为准。
指定最大字段宽度将防止堆栈溢出
scanf("%1023s", buf);
为了确保打印时堆栈不会溢出,请使用memset:
memset(buf,0,1024);
因此,程序将是:
#include <stdio.h>
#include <string.h>
int main()
{
char buf[1024];
memset(buf,0,1024);
scanf("%1023s", buf);
printf("----> %s", buf);
return 0;
}