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