使用scanf格式错误输出(黑客:剥削艺术示例)

时间:2017-05-30 14:16:51

标签: c linux gcc

我正在阅读“黑客:剥削艺术”一书。我现在只在开头的章节中,它正在用C语言进行一些基本的字符串复制和输入功能。

最新的示例使用strcpy和scanf的组合来重复打印字符串,但在编译时,会为我生成格式错误的输出。示例如下:

Input.c中:

#include <stdio.h>
#include <string.h>
int main() {
    char message[10];
    int count, i;

    strcpy(message, "Hello, world!");

    printf("Repeat how many times? ");
    scanf("%d", &count);

    for(i=0; i < count; i++)
        printf("%3d - %s\n", i, message);
}

根据这本书,当你输入一个数字时,它应该多次打印。

例如:

reader@hacking:~/booksrc $ ./input
Repeat how many times? 3
0 - Hello, world!
1 - Hello, world!
2 - Hello, world!

这适合我,但不知怎的,“Hello,world!”字符串变得损坏和格式错误,只打印“Hello,wor”,然后打印错误的字符。

helpme@stackoverflow:~/booksrc $ ./input
Repeat how many times? 3
0 - Hello, wor
1 - Hello, wor␦
2 - Hello, wor␦

最后打印的错误字符似乎有一些一致性,好像它是通过UTF-8字符或类似的东西进行迭代。对于前三个,它将打印表示不可打印的Unicode字符的框,如果给出更高的范围,最终将开始打印真实字符。

我认为这与使用scanf和我的终端有关(我在Debian GNU / Linux机器上运行这个程序,使用默认的GNOME终端。)但我很好奇这个例子可能有什么在以前版本的gcc上工作而不是当前版本 - scanf在当前版本的C上有不同的解释吗?

至于其他信息,我正在运行gcc版本6.3.0。

如果有人能提供任何帮助,我们将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:3)

char message[10];
...
strcpy(message, "Hello, world!");

message不能包含整个Hello, world!,因为它很小。因此,您将遇到未定义的行为,这解释了您所看到的奇怪输出。您需要增加message的大小或动态确定其所需的大小,例如使用strlen

答案 1 :(得分:2)

您的问题是消息缓冲区的长度。字符串&#34; Hello,world!&#34;包含13个字符+ \0,其中strcpy会自动添加,因此最终长度为14.以下是代码:

#include <stdio.h>
#include <string.h>
int main() {
    char message[14];
    int count, i;

    strcpy(message, "Hello, world!");

    printf("Repeat how many times? ");
    scanf("%d", &count);

    for(i=0; i < count; i++)
        printf("%3d - %s\n", i, message);
}

提示:最好使用strnlen而不是strlen。

答案 2 :(得分:0)

echo "Hello, world!" | wc
      1       2      14

所以你的字符串最后0有14 + 1个字节,你试着将它保存在10个字节的数组中。

strcpy会产生溢出。