c – 可寻址存储器以及与缓冲区溢出的关系

c – 可寻址存储器以及与缓冲区溢出的关系,第1张

概述阅读缓冲区溢出,我遇到了下面给出的示例代码: – void function(int a, int b, int c) {char buffer1[5];char buffer2[10];}void main() { function(1,2,3);} 这是来自着名的粉碎堆栈的乐趣和利润文章我猜. (参考:http://insecure.org/stf/smashstack.html 阅读缓冲区溢出,我遇到了下面给出的示例代码: –
voID function(int a,int b,int c) {char buffer1[5];char buffer2[10];}voID main() { function(1,2,3);}

这是来自着名的粉碎堆栈的乐趣和利润文章我猜. (参考:http://insecure.org/stf/smashstack.html)

文章说,要为buffer1和buffer2分配空间,需要20个字节(缓冲区1为8个字节,缓冲区2为12个字节),因为只能以字大小的倍数访问存储器地址(在这种情况下,1个字= 4个字节).

但我记得内存是字节可寻址的.我可以从内存中一次访问1个字节.我将此与处理器的位数相关联.例如一个32位处理器可以访问2 ^ 32个内存位置,并且由于1个内存位置保持1个字节(8位),32位处理器的总可寻址内存等于(2 ^ 32)/(1024 * 1024 * 1024)= 4096 MB = 4GB.

因为在上面的例子中,buffer1和buffer2都是char类型,假设需要1个字节,为什么我们不能分别为buffer1和buffer2分配5个字节和10个字节?

为什么内存访问限制为字大小的倍数?

解决方法 首先 – 内存访问不仅限于字大小.

正如您所指出的,您可以自由地以各自cpu支持的最细粒度访问内存 – 在大多数情况下,这将是字节.

但是对于C中的局部变量,对齐规则有点具体.
整个单词访问限制与函数本地放置在所谓的堆栈上的事实有关.

堆栈由cpu提供,以临时存储和检索存储器中的寄存器值,并且每个程序都有自己的存储器以用作堆栈空间.
在某些情况下,通常需要以您的cpu使用的寄存器大小访问堆栈,因此您不会意外地破坏cpu使用的推送/d出访问.
在32位系统上,访问大小为每个寄存器4个字节,64位为8位.

因此在您的示例中,函数的堆栈在Intel cpu上可能看起来像这样(取决于 *** 作系统):

|---   function's stack bottom  ---|| 4 byte Code-Segment index        || 4 byte return address            || 4 byte buffer1[0..3]             || 1 byte buffer1[4],3 byte pad || 4 byte buffer2[0..3]             || 4 byte buffer2[4..7]             || 2 byte buffer2[8..9],2 byte pad ||---   function's stack top     ---|

填充字节是必需的,这样当程序运行并使用函数内部的堆栈时,它仍然可以正确对齐(相信我会使用它很多;)).

例如.推/d仍然会产生4字节对齐的地址.

请记住:此对齐规则仅适用于堆栈空间 – 全局或静态变量可以位于奇数存储器位置(不太可能,但可能)

我希望这不是技术/低级别的.

[编辑]如果您考虑以下事情,那么缓冲区溢出的关系变得清晰:如果你知道内存和堆栈布局,你可以 *** 作返回地址之类的东西.正如您所看到的那样,通过过度/下溢缓冲区,您可以轻松地更改堆栈上方/下方的值.在大多数情况下,这会使代码崩溃,但如果执行得当,您还可以将一些可执行代码放在堆栈中/内存中的某处,并更改函数的返回地址以跳转到该代码,而不是返回到调用它的位置.

总结

以上是内存溢出为你收集整理的c – 可寻址存储器以及与缓冲区溢出的关系全部内容,希望文章能够帮你解决c – 可寻址存储器以及与缓冲区溢出的关系所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1244345.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存