C语言 什么是堆栈粉碎(C)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40416516/
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
what is stack smashing (C)?
提问by Gonzalez
Code:
代码:
int str_join(char *a, const char *b) {
int sz =0;
while(*a++) sz++;
char *st = a -1, c;
*st = (char) 32;
while((c = *b++)) *++st = c;
*++st = 0;
return sz;
}
....
char a[] = "StringA";
printf("string-1 length = %d, String a = %s\n", str_join(&a[0],"StringB"), a);
Output:
输出:
string-1 length = 7, char *a = StringA StringB
*** stack smashing detected **** : /T02 terminated
Aborted (core dumped)
string-1 长度 = 7,char *a = StringA StringB
*** 检测到堆栈粉碎 **** : /T02 终止
中止(核心转储)
I don't understand why it's showing stack smashing? and what is *stack smashing? Or is it my compiler's error?
我不明白为什么它显示堆栈粉碎?什么是*stack smashing?还是我的编译器的错误?
回答by Sourav Ghosh
Well, stack smashingor stack buffer overflowis a rather detailed topic to be discussed here, you can refer to this wiki articlefor more info.
好吧,堆栈粉碎或堆栈缓冲区溢出是这里要讨论的一个相当详细的主题,您可以参考这篇 wiki 文章了解更多信息。
Coming to the code shown here, the problem is, your array ais not large enough to hold the final concatenated result.
来到这里显示的代码,问题是,您的数组a不够大,无法保存最终的连接结果。
Thereby, by saying
因此,通过说
while((c = *b++)) *++st = c;
you're essentially accessing out of bound memory which invokes undefined behavior. This is the reason you're getting the "stack smashing" issue because you're trying to access memory which does not belong to your process.
您实际上是在访问调用未定义行为的越界内存。这就是您遇到“堆栈粉碎”问题的原因,因为您正在尝试访问不属于您的进程的内存。
To solve this, you need to make sure that array acontains enough space to hold both the first and second stringconcatenated together. You have to provide a larger destination array, in short.
要解决这个问题,您需要确保数组a包含足够的空间来保存连接在一起的第一个和第二个字符串。简而言之,您必须提供更大的目标数组。
回答by mtraceur
Stack smashing means you've written outside of ("smashed" past/through) the function's storage space for local variables (this area is called the "stack", in most systems and programming languages). You may also find this type of error called "stack overflow" and/or "stack underflow".
堆栈粉碎意味着您已经在函数的局部变量存储空间之外(“粉碎”过去/通过)写入(在大多数系统和编程语言中,该区域称为“堆栈”)。您可能还会发现这种称为“堆栈溢出”和/或“堆栈下溢”的错误类型。
In your code, C is probably putting the string pointed to by aon the stack. In your case, the place that causes the stack-smash is when you increment stbeyond the original apointer and write to where it points, you're writing outside the area the C compiler guarantees to have reserved for the original string assigned into a.
在您的代码中,C 可能将指向的字符串a放在堆栈上。在您的情况下,导致堆栈粉碎的地方是当您增加st超出原始a指针并写入它指向的位置时,您正在写入 C 编译器保证为分配给的原始字符串保留的区域之外a。
Whenever you write outside an area of memory that is already properly "reserved" in C, that's "undefined behavior" (which just means that the C language/standard doesn't say what happens): usually, you end up overwriting something else in your program's memory (programs typically put other information right next to your variables on the stack, like return addresses and other internal details), or your program tries writing outside of the memory the operating system has "allowed" it to use. Either way, the program typically breaks, sometimes immediately and obviously (for example, with a "segmentation fault" error), sometimes in very hidden ways that don't become obvious until way later.
每当您在 C 中已经正确“保留”的内存区域之外写入时,这就是“未定义的行为”(这只是意味着 C 语言/标准没有说明会发生什么):通常,您最终会覆盖其他内容您的程序的内存(程序通常将其他信息放在堆栈上的变量旁边,例如返回地址和其他内部详细信息),或者您的程序尝试在操作系统“允许”它使用的内存之外写入。无论哪种方式,程序通常都会中断,有时会立即且明显(例如,出现“分段错误”错误),有时会以非常隐蔽的方式中断,直到后来才变得明显。
In this case, your compiler is building your program with special protections to detect this problem and so your programs exits with an error message. If the compiler didn't do that, your program would try to continue to run, except it might end up doing the wrong thing and/or crashing.
在这种情况下,您的编译器正在构建具有特殊保护的程序以检测此问题,因此您的程序退出并显示错误消息。如果编译器没有这样做,您的程序将尝试继续运行,除非它最终可能会做错事和/或崩溃。
The solution comes down to needing to explicitly tell your code to have enough memory for your combined string. You can either do this by explicitly specifying the length of the "a" array to be long enough for both strings, but that's usually only sufficient for simple uses where you know in advance how much space you need. For a general-purpose solution, you'd use a function like mallocto get a pointer to a new chunk of memory from the operating system that has the size you need/want once you've calculated what the full size is going to be (just remember to call freeon pointers that you get from mallocand similar functions once you're done with them).
解决方案归结为需要明确告诉您的代码为您的组合字符串提供足够的内存。您可以通过显式指定“a”数组的长度来完成此操作,使其对于两个字符串都足够长,但这通常仅适用于您事先知道需要多少空间的简单使用。对于通用解决方案,您将使用一个函数,例如malloc从操作系统获取指向新内存块的指针,一旦您计算出完整大小将是什么(只需记住调用free您从中获得的指针malloc和完成使用它们后的类似函数)。

