Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 内存将通过代码中的溢出覆盖什么_C++_C_Arrays_Memory - Fatal编程技术网

C++ 内存将通过代码中的溢出覆盖什么

C++ 内存将通过代码中的溢出覆盖什么,c++,c,arrays,memory,C++,C,Arrays,Memory,我得到了以下代码: char *func(char * a) { char b[1000]; strcpy(b,a); return b; } (我知道代码不好,因为我返回了数组的地址,当我退出函数时,该地址将被删除。)我的问题是,如果我输入“a”,一个2000个字符的数组,“b”仅为1000个字符的数组,将删除/覆盖什么。我在某个地方读到这个问题,他们说通过这个代码,我可以知道什么会被覆盖 如果我在“a”中输入2000个字符的数组,“b”仅为1000个字符的数组,将删除/覆盖哪些内容 这种行

我得到了以下代码:

char *func(char * a)
{
char b[1000];
strcpy(b,a);
return b;
}
(我知道代码不好,因为我返回了数组的地址,当我退出函数时,该地址将被删除。)我的问题是,如果我输入“a”,一个2000个字符的数组,“b”仅为1000个字符的数组,将删除/覆盖什么。我在某个地方读到这个问题,他们说通过这个代码,我可以知道什么会被覆盖

如果我在“a”中输入2000个字符的数组,“b”仅为1000个字符的数组,将删除/覆盖哪些内容

这种行为没有定义。从标准的角度来看,没有任何保证。某些内存可能会被覆盖,也可能不会被覆盖。实际上,一些内存可能会被覆盖

如果我错了,请纠正我,说明此溢出将重写指针的值。对吧?

可以。可能不会。这种行为没有定义

将发生的情况取决于编译器、编译器版本、cpu体系结构、编译选项、如何定义程序的其余部分以及可能的其他因素


在典型的实现中,返回值适合于寄存器,并且是编译时常量,因此在实践中,它不太可能存储在堆栈上,在这种情况下,它不会受到溢出的影响。还有更危险的潜在副作用,例如函数返回的位置与调用它的位置完全不同。

如果您传递的
a
中的C字符串大于为
b
分配的空间(1000字节)它将愉快地写过
b
的末尾,并向下通过
b
下面堆栈上的任何内容。C字符串没有定义的长度
strcpy(b,a)
将继续将字节复制到
b
中,直到在
a
中找到
\0
。在函数
func
的堆栈上,编译器将为
b
保留1000字节,然后将返回地址保存到调用的
func
中。如果
a
覆盖
b
您将写入返回地址,当
func
返回时,您将跳转到某个随机地址,并产生可怕的结果。每个编译器都可以将函数的返回地址放在它喜欢的任何地方。也许它会将返回地址放在堆栈的顶部。但即使在这种情况下,你也会写一些你不应该写的东西。如果你幸运的话,你会被侵犯访问权限

为了防止出现这种情况,您可以使用strncpy(b,a,sizeof(b)-1)并将
\0
放在
b
的末尾。如果
strlen(a)>sizeof(b)-1,最好检查
strlen(a)
,并正确处理错误

这正是黑客用来打破Windows安全限制的“缓冲区溢出”技术。您调用的Windows函数需要C字符串,但不检查传入的C字符串的长度。传入的字符串猜测输入缓冲区的长度,最终正确猜测并覆盖函数的返回地址,以指向传入的字符串。输入字符串的其余部分包含在Windows函数的安全权限下运行的机器代码指令。然后它可以做它想做的任何事情


Microsoft很久以前就关闭了这个安全漏洞,但检查接受作为输入参数的C字符串的长度仍然是一个很好的教训。

您似乎不熟悉堆栈的概念。当程序控件进入一个函数时,一个指向堆栈的指针被赋予程序控件。所有的局部变量都分配在这个堆栈上。当程序从函数返回时,堆栈指针将更改为其原始值。因此,b位于堆栈上,并为其分配1000字节。当程序从func返回时,实际上在其他函数使用堆栈区域之前,不会删除或覆盖任何内容。您可以在退出函数后尝试访问“b”,它必须工作。但是假设调用FUNC之后,调用另一个函数“FUNC1”,它有一些局部变量,然后更新这些变量将覆盖B指向“/P>”的内容。“未定义行为”的定义意味着C++中的行为是未定义的。这个问题的答案和“黑洞中的什么”的答案一样,“代码> B <代码>的值在返回时将为空。@ SAMVALSHIVCHK,你如何知道它的C++,它标记了C++和C.@ SAMVARSHIVCHK,这是一本可靠的书,它说,通过这个函数,我可以知道什么会覆盖。我也觉得很奇怪,但我觉得我错过了什么。也许我们都有?或者它只是一个糟糕的问题检查此页,用于演示错误的示例几乎与示例代码相同:如果您检查接受作为输入参数的C字符串的长度,则在复制它们时不需要检查溢出。那种
strncpy
舞蹈几乎总是不明智的(因为大多数人做得不对),而且,如果你写了正确的代码(正如你所建议的),你就不需要它了。