C语言 错误:变量“字符串”周围的堆栈已损坏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4644475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Error: Stack around the variable 'string' was corrupted
提问by Ordo
I've a small problem with the code below. It is a simple program which reads in 2 arrays of char and an int. Then it stores all the content into another string and prints it out.
下面的代码有一个小问题。这是一个简单的程序,它读入 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;
}
Now the program is running fine, but when i close it, i get the following error: Run-Time Check Failure #2 - Stack around the variable 'string' was corrupted.That's a bit confusing and i can't figure out where the problem is. I would be thankful for any advice.
现在程序运行良好,但是当我关闭它时,出现以下错误: 运行时检查失败 #2 - 变量“字符串”周围的堆栈已损坏。这有点令人困惑,我无法弄清楚问题出在哪里。我将不胜感激任何建议。
回答by Mitch Wheat
You are writing more characters into 'string' than it has room allocated for (i.e. more than 50)
您在“字符串”中写入的字符多于分配的空间(即超过 50 个)
There are 37 characters in "Your name is %s %s and you are %d years old."BEFORE you add the values for first, last and age. That leaves just 13 chars for all three variables. So it spills over into the other vars declared after your variable 'string' on the stack.
在"Your name is %s %s and you are %d years old."添加 first、last 和 age 值之前,有 37 个字符。这三个变量只剩下 13 个字符。因此,它会溢出到堆栈上变量“字符串”之后声明的其他变量中。
As Jon mentioned, it is best practice to use the functions that limit how much they write (the 'n' variants), otherwise these can be sources of bufferoverrun exploits.
正如 Jon 提到的,最佳实践是使用限制写入量的函数('n' 变体),否则这些函数可能成为缓冲区溢出漏洞利用的来源。
BTW 'string' is a very poor name for a variable.
顺便说一句,'string' 是一个非常糟糕的变量名称。
回答by Jon Skeet
Aside from anything else, you've allowed for a first name of up to 10 characters and a last name of up to 15 characters. If those limits are reached (but not exceeded) and the age is a two digit number, that will take 66 characters - so you would have to declare stringto be an array of 67 characters to cope (to include the null terminator).
除此之外,您还允许最多 10 个字符的名字和最多 15 个字符的姓氏。如果达到(但未超过)这些限制并且年龄是两位数,则需要 66 个字符 - 因此您必须声明string为 67 个字符的数组来应对(包括空终止符)。
Beyond that, you should be using functions or format strings which allow you to limit the size of the input - currently if someone enters a first name of longer than 10 characters (etc) you'll trample over other bits of memory. It's been a while since I've written any C, but using format strings of "%10s" and "%15s" may help in this respect - or use fgets.
除此之外,您应该使用允许您限制输入大小的函数或格式字符串 - 目前,如果有人输入超过 10 个字符(等)的名字,您将践踏其他内存位。自从我写任何 C 以来已经有一段时间了,但是使用“%10s”和“%15s”的格式字符串可能会在这方面有所帮助 - 或者使用fgets.
Likewise, I would suggest using snprintf(or snprintf_sif it's available to you) instead of sprintfto avoid the overrunning-output problem. Use the return values of all of these methods to detect errors, too :)
同样,我建议使用snprintf(或者snprintf_s如果它对您可用)而不是sprintf避免溢出输出问题。也可以使用所有这些方法的返回值来检测错误:)
回答by Alex Budovski
You can limit the amount of chars scanf reads with
您可以限制字符 scanf 读取的数量
scanf("%9s", foo)
which will read at most 9 characters, then append a NUL, which is suitable for a buffer of size 10.
它最多读取 9 个字符,然后附加一个 NUL,这适用于大小为 10 的缓冲区。
回答by martin clayton
I'd guess it's something to do with the fact that the length of the stringarray is 50 chars, you have in the sprintf 37 (if I counted right) plus then up to 11 for firstand another 16 for last, plus maybe 2 or 3 for age. That adds up to more than 50. Everything works ok, but you're very likely overwriting beyond the end of the 50 chars allocated. That will 'work', but corrupt the stack, as you have observed.
我猜这与string数组的长度为 50 个字符有关,您在 sprintf 中拥有 37 个字符(如果我算对了)加上最多 11 个 forfirst和另外 16 个 for last,再加上 2 或 3 个 for年龄。加起来超过 50 个。一切正常,但您很可能会在分配的 50 个字符结束后进行覆盖。正如您所观察到的那样,这将“起作用”,但会破坏堆栈。

