【问题标题】:Where does variable length array/alloca allocate in stack可变长度数组/alloca 在堆栈中分配的位置
【发布时间】:2023-03-30 23:06:01
【问题描述】:

我真的很好奇alloca() 函数是如何工作的,因此我编写了一个简单的测试程序如下:

int test() {
    int a = 0;
    int e;
    char tmp2[a]; //alloca
    int d;
    char* tmp3 = new char[2];
    tmp2[100] = 1;
    return 0;
}

int main(int argc, char** argv) {
    test();
    return 0;
}

根据文档,alloca() 将在堆栈中分配内存。我使用 gdb 运行程序,发现(char*)&tmp2 - (char*)a = -44 表示它们之间有 44 个字节,而e-ad-etmp3-d 的地址之间的距离是 4 个字节。我真的不明白编译器如何在堆栈中分配可变长度数组,希望有人能告诉我44字节的含义。

【问题讨论】:

  • 您的代码不包含对名为alloca 的函数的调用。但是,它确实包含new,它动态分配内存。这不会发生在“堆栈”上。
  • 你的测试根本没有调用alloca()...
  • 很抱歉,我使用的是 \"char tmp2[a];"它分配一个可变长度数组,就像 alloca 所做的一样
  • 选择一种语言 - new 是 C++ 而 VLA 是 C99。两者不相容。
  • 我猜你假设 GCC 的 VLA 实现使用 alloca?

标签: c c99 variable-length-array


【解决方案1】:
char tmp2[a];

其中a 是一个非常量整数,使用称为可变长度数组VLAs 的C99 功能。

该功能在标准 C++ 中不可用,尽管它是 g++ 编译器在非标准模式下支持的语言扩展。

未指定如何为 VLA 分配内存。它可能在机器堆栈上,例如alloca,也可能是动态分配的内存。

【讨论】:

    【解决方案2】:

    alloca() 不是标准的一部分。它被认为是编译器/机器相关的。因此,内在函数仅属于实现。

    话虽如此,如果我们谈论 x86 机器,那么堆栈操作是通过使用专用堆栈指针寄存器 - sp / esp / rsp(16/32/64 位代码)完成的,其中包含推入堆栈的最后一个字/双字/四字的地址。要保留更多内存,我们只需从sp 寄存器中减去一些值。

    因此,x86 中的“典型”alloca(x) 实现只是一条 CPU 指令:sub sp, x

    【讨论】:

    • 但是在我的测试中,x只有0,所以为什么要移动44个字节
    • @TruongHua 看看你的编译器的汇编输出,看看它生成了什么指令。
    • @TruongHua 只有拆机才能说明真相。编译器根本没有义务保持声明的顺序。
    • 不是一条指令;它必须将分配大小四舍五入到 16 字节的倍数以保持堆栈对齐。
    猜你喜欢
    • 2016-01-06
    • 1970-01-01
    • 2012-01-28
    • 2018-03-09
    • 2014-09-18
    • 1970-01-01
    • 2014-03-04
    • 2013-05-16
    • 2013-12-08
    相关资源
    最近更新 更多