错误:变量'string'周围的堆栈已损坏

时间:2011-01-10 07:11:23

标签: c

下面的代码我遇到了一个小问题。这是一个简单的程序,它读入2个char和int数组。然后它将所有内容存储到另一个字符串中并将其打印出来。

#include <stdio.h>
#include <string.h>

int main ()

{
    char string [50];
    char first [11]; 
    char last [16];
    int age = 0;


    printf("Please type in your first name: ");
        scanf("%s", first); 

    printf("Please type in your last name: ");
        scanf("%s", last); 

    printf("Please type in your age: ");
        scanf("%d", &age); 

    sprintf(string, "Your name is %s %s and you are %d years old.", first, last, age);
        puts(string);

    getchar();
    getchar();

    return 0;
}

现在程序运行正常,但是当我关闭它时,我收到以下错误: 运行时检查失败#2 - 变量'string'周围的堆栈已损坏。 这有点令人困惑,我无法弄清楚问题出在哪里。我会感激的 任何建议。

4 个答案:

答案 0 :(得分:14)

您在“字符串”中写入的字符多于分配空间(即超过50个)

在添加first,last和age的值之前,"Your name is %s %s and you are %d years old."中有37个字符。这为所有三个变量留下了13个字符。所以它会溢出到堆栈上变量'string'之后声明的其他变量。

正如Jon所说,最佳做法是使用限制写入量的函数('n'变体),否则这些函数可能是缓冲区漏洞利用的来源。

BTW'string'是一个非常糟糕的变量名称。

答案 1 :(得分:4)

除了其他任何内容之外,您还允许使用最多10个字符的姓氏和最多15个字符的姓氏。如果达到(但未超过)这些限制且年龄为两位数,则需要66个字符 - 因此您必须将string声明为67个字符的数组才能应对(包括空值)终止子)。

除此之外,您应该使用函数或格式化字符串,这些字符串允许您限制输入的大小 - 当前如果有人输入超过10个字符(等)的名字,您将践踏其他内存。我写了任何C已经有一段时间了,但使用格式字符串“%10s”和“%15s”可能在这方面有所帮助 - 或者使用fgets

同样,我建议使用snprintf(或snprintf_s,如果它可供您使用)而不是sprintf,以避免超出输出问题。使用所有这些方法的返回值来检测错误:)

答案 2 :(得分:2)

您可以使用

限制字符scanf读取的数量
scanf("%9s", foo)

最多可读取9个字符,然后附加NUL,适用于大小为10的缓冲区。

答案 3 :(得分:1)

我猜这与string数组的长度为50个字符这一事实有关,你在sprintf 37(如果我算对了)加上然后高达11 {{1另外16 first,加上年龄可能是2或3。一共工作正常,一切正常,但你很可能在分配的50个字符结束后覆盖。正如你所观察到的那样,这将“有效”,但会破坏堆栈。