堆栈、内存堆和汇编代码的关系
The relation of Stack, Memory Heap and assembly code
我试图更详细地了解C/C++代码的编译过程及其内存管理。假设以下代码:
#include <iostream>
int main() {
int a = 5;
int *b = (int *) malloc(40);
return 0;
}
我知道a
和b
将在堆栈上创建,b
(它指向的内存)的值将在堆上。
编译成程序集的代码如下所示:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl $40, %eax
movl %eax, %edi
movl $0, -4(%rbp)
movl $5, -8(%rbp)
callq _malloc
xorl %ecx, %ecx
movq %rax, -16(%rbp)
movl %ecx, %eax
addq $16, %rsp
popq %rbp
retq
我的问题是;
a is on the stack (memory)
在这里是什么意思?根据上述汇编,a
直接嵌入到指令$5, -8(%rbp)
中,没有对存储器位置的引用。如果它在内存中,那么a
的地址是什么?
我知道_malloc
在堆(内存)上创建了40个字节,并返回了第一个内存地址,但我看不出堆栈是如何填充的,除了从中提取的指令本身之外,这里没有与内存的交互。
堆栈(内存)上的is在这里意味着什么?
这意味着由变量命名的对象存储在称为堆栈的内存部分,也称为调用堆栈。调用堆栈包含函数的局部自动变量。
movl $5, -8(%rbp)
rbp
是帧指针。它指向调用堆栈的当前帧。此指令将常量5移动到rbp指向的内存,偏移量为-8字节。换句话说,此指令初始化堆栈上的变量a
。
如果它在内存中,那么a的地址是什么?
a
的地址看起来是rbp - 8
,其中rbp
是存储在帧指针中的地址。在C++领域中,您可以使用addressof运算符来获取地址。
堆栈(与内存有关)、堆、frame和rbp等都不是由C++语言定义的。这些词在特定CPU体系结构的上下文中具有意义。
语言中没有任何内容表明a
将在堆栈上。编译器有权把它放在任何它想放的地方;特别是,如果它不需要把它放在任何地方,它就不必。
变量a
在放入5之后就再也不用了,所以一个好的优化器会完全放弃这一行。
然而,在您的特定情况下,在我看来a
确实在堆栈中。它位于%rbp中的帧指针外-8字节处。也就是说,a
的地址是-8(%rbp),或者"寄存器rbp中的值,减去8",这非常接近堆栈的顶部。
获取更多详细信息。堆栈存在于内存中。让我们假设堆栈在内存中向下增长(这是传统的),这样堆栈的"顶部"就会向更小的地址增长。有一个指向堆栈顶部的"堆栈指针",即添加到堆栈中的最后一个东西的地址(我在这里只是泛泛地说)。
要分配N个字节的堆栈空间,所需要的就是从堆栈指针中减去N。生成的代码通常在一条指令中完成这一操作,因为它知道所输入函数所需的总空间。为了释放该空间,代码可以(a)添加N,或者(b)恢复堆栈指针的减法前值,该值已保存在某个位置。选择实际上是定义了编译器系统希望如何管理堆栈的更精细的细节。
堆栈管理中可能会用到一些辅助寄存器。一个常见的是有一个"框架指针",这是%rbp在这里所扮演的角色。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- Objective-C源代码和clang -rewrite-objc C++代码之间有什么关系?
- 堆栈、内存堆和汇编代码的关系
- Visual Studio 中C++代码的变量依赖关系图
- 在C++中,当对象关系不直观时,如何重用代码?
- 两个类中的循环依赖关系 - 代码无法编译
- 如何在单击mfc代码中的关系文件时获取文件名
- 代码::阻止项目之间的依赖关系
- 如何将一系列if/else-if/else-if/关系链转换为线性循环代码