我正在阅读缓冲区溢出。 我发现有关堆栈上局部变量的内存分配的一个奇怪的事情
int f1 () { char string1[12]; char string2[4]; }
这里分配发生在堆栈上。
现在,在GCC中, string2被分配了4个字节,但是如果我声明除了2的幂(最多16个)之外,那么它由编译器分配16个字节。 这意味着如果我在3,5,6,7,….,15个字节中分配string2,那么它由编译器分配16个字节,但如果我分配2的幂,如1,2,4,8 ……然后它被分配完全相同的大小。 如果我分配超过16个字节(不是2的幂),那么它分配32个字节(我估计高达32个字节)。
而在Visual Studio中,如果我分配1个字节,则分配9个字节,如果从2-4个字节分配,则分配12个字节,如果从5-8个字节开始,则编译器分配16个字节。
任何人都知道为什么这样的任务???
Atleast在Visual Studio中,如果有缓冲区溢出,我会收到调试错误,但在gcc中没有任何反应。 GCC仅在发生过大的溢出时才提供分段故障。
堆栈帧大小受存储器对齐选择的影响,对于32位代码通常是4的倍数,对于64位代码通常是8的倍数。
两个编译器都可以包括使用canary进行堆栈帧损坏检查,在函数入口处初始化并在函数出口处检查的堆栈顶部的额外32位值。 如果更改了canary值,则会发生程序中止,因为堆栈帧可能被恶意代码损坏,可能会更改函数返回地址并使其返回到任意位置。 一个非常流行的恶意软件注入矢量。
MSVC具有/ RTC选项,默认情况下在调试配置中启用。 在每个局部变量之间添加这些金丝雀。 因此它可以检测每个变量上的缓冲区溢出问题。
这些金丝雀当然需要额外的空间,影响堆栈框架的大小。
多数民众赞成由于记忆 – 对齐 。 CPU更容易访问内存地址,这是所请求数据大小的倍数。
因此,编译器使用明确的字节填充结构以对齐结构。 例如:
struct foo { char a int b , c; short d; bool e; double f; };
理论上,该结构的大小是(假设bool
的大小是1字节, char
1字节, int
4字节, short
2字节, double
8字节)20字节。 但实际上,编译器会在结构中添加“空洞”以对齐内存:
0 | 1 | 2 | 3 -----------+---+---+--- 0x0000 | a | | | -----------+---+---+--- 0x0004 | b | b | b | b -----------+---+---+--- 0x0008 | c | c | c | c -----------+---+---+--- 0x000C | d | d | | -----------+---+---+--- 0x0010 | e | | | -----------+---+---+--- 0x0014 | f | f | f | f -----------+---+---+--- 0x0018 | f | f | f | f -------+---+---+---+---
我记得这是优化的原因,也许是因为要解决这个问题。 像这样的另一个例子是布尔类型,它通常消耗8位而且可能只有一个。 这可能与不同的编译器有很大不同。 你可以在c ++中找到更多关于为什么char和bool大小相同的boolean ?
需要了解更多c/c++开发分享为什么在堆栈中为局部变量分配的内存多于C ++中所需的内存?,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!
以上就是c/c++开发分享为什么在堆栈中为局部变量分配的内存多于C ++中所需的内存?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/978820.html