运行时检查失败 #2 - 变量“cid1”周围的堆栈已损坏

Posted

技术标签:

【中文标题】运行时检查失败 #2 - 变量“cid1”周围的堆栈已损坏【英文标题】:Run-Time Check Failure #2 - Stack around the variable 'cid1' was corrupted 【发布时间】:2013-02-18 22:25:35 【问题描述】:

我是 C 编程新手,目前正在大学上课。我遇到了这个错误,并且不确定如何在谷歌数小时后修复它。我正在创建一个打印成绩报告并不断遇到此错误的程序。

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main (void)
   char Name[20];
    char cid1[5]="", cid2[5]="", cid3[5]="", cid4[5]="", cid5[5]="", cid6[5]="";
    char Description1[20]="", Description2[20]="", Description3[20]="", Description4[20]="", Description5[20]="", Description6[20]="";
    int hrs1 = 0, hrs2=0, hrs3=0, hrs4=0, hrs5=0, hrs6=0;
    char grade1[1]="",grade2[1]="",grade3[1]="",grade4[1]="",grade5[1]="",grade6[1]="";

    printf("Enter Students Name ");
    gets(Name);

    printf("Enter Class ID ");
    scanf("%s", &cid1);

    printf("Enter Class Description ");
    gets(Description1);

    printf("%s", Name);
    printf("%s", cid1);
    printf("%s", Description1);

    system("pause");

【问题讨论】:

你输入了什么值? 如果是 C,为什么还要有 C++ 标签? 【参考方案1】:
scanf("%s", &cid1);

您需要致电:

scanf("%s", cid1);

并且您的数组被声明为5 元素的大小,因此如果您传递的字符数超过4(您必须计算尾随的\0),您将调用未定义的行为。

【讨论】:

应该没关系。指针地址相同,但类型不同。 @nneonneo:你说得对,它不会对大多数实现产生影响,但只是为了记录,它确实会导致未定义的行为。【参考方案2】:

您只能读取数组支持的内容。如果您声明一个 char 数组有 5 个字节(char cid1[5]),那么您最多可以输入 4 个字符(第 5 个是空终止符)。如果您输入更多,您将破坏内存并收到该消息。

gets 也是一个非常不安全的函数,用于从输入中读取字符串,因为无法避免缓冲区溢出。 从不使用它。使用fgets 代替stdin

【讨论】:

请注意,scanf%s(并且没有指定长度,即 %s 而不是 %4s)与 gets 一样不安全。 @nneonneo 成功了!我会改用 fgets,谢谢!不过,还有一个快速的问题,在调试和输入我的信息时,我无法输入我的课程描述。它甚至没有给我提示。一旦我输入我的 cid1 后按 enter,它会打印我的名字和 cid1 以及描述应该去的空格【参考方案3】:

我不确定这是否是唯一的问题,但我马上就可以看到字符串分配存在问题。

请记住,C 中的字符串存储为一系列 char 值,以 0 结尾。这意味着五位数的课程名称将需要六个字符来保存它...类似于 'C', 'S '、'1'、'0'、'1'、'\0' 。这也意味着以字符串形式显示的单个数字等级将需要两个字符。

由于gets() 函数将该零附加到字符串的末尾,因此您的grade1[1] 数组(作为一个示例)正在溢出。它被声明保存一个字符,但正在写入两个字符。除其他外,这最终会破坏您的堆栈。我会将所有数组的大小至少再增加一个字符。

另一个问题是您没有错误检查,因此可能有人会输入超过 20 个字符的名称并导致错误,但这可能只是因为您仍在学习基础知识。在“真实”代码中,您可能永远不会使用gets()。

【讨论】:

以上是关于运行时检查失败 #2 - 变量“cid1”周围的堆栈已损坏的主要内容,如果未能解决你的问题,请参考以下文章

c++ 运行时检查失败 #2 - 变量“ToSend22”周围的堆栈已损坏

运行时检查失败 #2 - 变量“primes”周围的堆栈已损坏

运行时检查失败 #2 - 变量周围的堆栈已损坏

运行时检查失败 #2 - 变量“l1”周围的堆栈已损坏

运行时检查失败 #2 - 变量“索引”周围的堆栈已损坏

运行时检查失败 #2 - 变量“e_color”周围的堆栈已损坏