C++ 内存分配意味着什么
考虑以下几行:C++ 内存分配意味着什么,c++,allocation,C++,Allocation,考虑以下几行: int v[100]; 此行分配100*sizeof(int)内存字节。但如果我们正在寻找这一行的反汇编,那么它背后就没有代码。那么,内存分配是在没有机器指令的情况下执行的吗?我很困惑…这取决于上下文,但您最可能谈论的是堆栈分配内存/自动变量,如下所示: int fn() { int v[100]; ... } 如果查看fn的反汇编,您应该注意到函数序言中从esp寄存器中减去了一些值 比如说, sub esp, 190h 这是您正在寻找的分配。该变量存储在堆
int v[100];
此行分配
100*sizeof(int)
内存字节。但如果我们正在寻找这一行的反汇编,那么它背后就没有代码。那么,内存分配是在没有机器指令的情况下执行的吗?我很困惑…这取决于上下文,但您最可能谈论的是堆栈分配内存/自动变量,如下所示:
int fn()
{
int v[100];
...
}
如果查看fn
的反汇编,您应该注意到函数序言中从esp
寄存器中减去了一些值
比如说,
sub esp, 190h
这是您正在寻找的分配。该变量存储在堆栈上,因此通过移动堆栈指针esp,您已经为它腾出了空间。这取决于上下文,但您最有可能谈论的是堆栈分配的内存/自动变量,如下所示:
int fn()
{
int v[100];
...
}
如果查看fn
的反汇编,您应该注意到函数序言中从esp
寄存器中减去了一些值
比如说,
sub esp, 190h
这是您正在寻找的分配。该变量存储在堆栈上,因此通过移动堆栈指针,
esp
,您已经为它腾出了空间。在编译器中,局部变量分配被转换为alloca
(或“堆栈分配”),也就是说,假设该变量未“未使用且未完全删除”,通常通过从函数开始处的堆栈指针中减去所需的总大小,然后在函数结束处重新添加(或恢复堆栈指针)来完成
这是类似上述函数的“LLVM IR”(IR=中间表示):
define i32 @fn() #0 {
%v = alloca [100 x i32], align 16
ret i32 42
}
在x86-64汇编程序中,它变成:
fn: # @fn
pushq %rbp
movq %rsp, %rbp
subq $272, %rsp # imm = 0x110
movl $42, %eax
addq $272, %rsp # imm = 0x110
popq %rbp
retq
fn: # @fn
.cfi_startproc
movl $42, %eax
retq
(不要问我为什么是272字节,而不是400字节——我真的不知道!)
如果我们使用-O2启用优化,它将变为:
fn: # @fn
pushq %rbp
movq %rsp, %rbp
subq $272, %rsp # imm = 0x110
movl $42, %eax
addq $272, %rsp # imm = 0x110
popq %rbp
retq
fn: # @fn
.cfi_startproc
movl $42, %eax
retq
换句话说,堆栈分配将完全消失
源代码:
int fn()
{
int v[100];
return 42;
}
在编译器中,局部变量分配被转换为
alloca
(或“堆栈分配”),也就是说,假设变量未“未使用且未完全删除”,通常通过从函数开头的堆栈指针中减去所需的总大小来完成,然后重新添加(或恢复堆栈指针)在函数的末尾
这是类似上述函数的“LLVM IR”(IR=中间表示):
define i32 @fn() #0 {
%v = alloca [100 x i32], align 16
ret i32 42
}
在x86-64汇编程序中,它变成:
fn: # @fn
pushq %rbp
movq %rsp, %rbp
subq $272, %rsp # imm = 0x110
movl $42, %eax
addq $272, %rsp # imm = 0x110
popq %rbp
retq
fn: # @fn
.cfi_startproc
movl $42, %eax
retq
(不要问我为什么是272字节,而不是400字节——我真的不知道!)
如果我们使用-O2启用优化,它将变为:
fn: # @fn
pushq %rbp
movq %rsp, %rbp
subq $272, %rsp # imm = 0x110
movl $42, %eax
addq $272, %rsp # imm = 0x110
popq %rbp
retq
fn: # @fn
.cfi_startproc
movl $42, %eax
retq
换句话说,堆栈分配将完全消失
源代码:
int fn()
{
int v[100];
return 42;
}
通常是函数序言。通常是函数序言。或者,他什么也看不到,因为未使用的变量v被删除了。你的意思是,对于每个开始执行的函数,我们都会在函数序言中声明每个变量吗?几乎。每个函数都有一个序言,其中设置寄存器和堆栈以供使用。有关详细信息,请参阅。对于要分配的总堆栈大小,每个函数只执行一次。因此,如果您有两个变量:
X
,大小为2字节,和Y
大小为4字节,那么您将得到一个子esp,6
。或者,他什么也看不到,因为未使用的变量v被删除了。你的意思是,对于每个开始执行的函数,我们都会在函数序言中声明每个变量吗?几乎。每个函数都有一个序言,其中设置寄存器和堆栈以供使用。有关详细信息,请参阅。对于要分配的总堆栈大小,每个函数只执行一次。因此,如果您有两个变量:X
,大小为2字节,和Y
大小为4字节,那么您将得到一个子esp,6
。