【问题标题】:C++: Function variable declarations, how does it work internally?C++:函数变量声明,它在内部是如何工作的?
【发布时间】:2011-05-24 16:14:55
【问题描述】:

这已经困扰我很久了:假设我有一个功能:

void test(){
    int t1, t2, t3;
    int t4 = 0;
    int bigvar[10000];
    // do something
}

计算机如何处理变量的内存分配?

我一直以为变量空间是保存在.exe中,然后电脑会读取,这样对吗?但据我所知,bigvar 数组在 .exe 中不占用 10000 个int 元素空间,因为它未初始化。那么当我调用函数时它的内存分配是如何工作的呢?

【问题讨论】:

  • exe存放在磁盘中,编译后的代码存放在那里。但是当它被执行时,它会从 processor 单元中获取内存。磁盘中的字节与变量所需的字节不对应。

标签: c++ windows visual-studio-2008 stack


【解决方案1】:

在一些旧的编译器上,我遇到了静态分配数组的行为。这意味着它在加载程序时为其预留内存,然后使用该空间。这种行为是不安全的(见 Sergey 的回答),我也不指望它会根据标准被允许,但我在野外遇到过。 (我不记得它是什么编译器。)

在大多数情况下,局部变量与返回地址和所有其他东西一起保存在堆栈中。这意味着未初始化的值可能包含敏感信息。根据 unwind 的回答,这也包括数组。

另一个有效的实现是在堆栈上找到的变量是一个指针,编译器在后台进行分配和解除分配(可能以异常安全的方式)。这将节省堆栈空间(必须在程序启动之前分配,并且不能轻易扩展用于 x86 架构)并且对于 C 标准 VLA(可变长度数组,又名穷人 std::vector)也非常有用

【讨论】:

    【解决方案2】:

    除了一些注释之外,我无法对已经说过的内容添加太多内容。您实际上可以将局部变量放入可执行文件中,并将它们分配在数据段(并初始化)而不是堆栈段中。为此,请将它们声明为 static。但是随后函数的所有调用将共享相同的变量,而在堆栈中每次调用都会创建一组新的变量。当多个线程同时调用该函数或存在递归时(尝试想象一下),这可能会导致很多麻烦。这就是为什么大多数语言使用堆栈作为局部变量,而static 很少使用。

    【讨论】:

      【解决方案3】:

      类似的局部变量通常使用处理器的stack 来实现。这意味着编译器唯一需要做的就是计算每个变量的大小,并将它们相加。总和是在函数入口处更改堆栈指针并在退出时更改回的量。然后访问每个变量,并将其相对偏移量访问到堆栈上的该内存块中。

      您的代码在 Linux 中编译时,在 x86 汇编器中最终看起来像这样:

      test:
              pushl   %ebp
              movl    %esp, %ebp
              subl    $40016, %esp
              movl    $0, -4(%ebp)
              leave
              ret
      

      在上面,常量 $40016 是四个 32 位整数 t1, t2, t3t4 所需的空间,而剩余的 40000 字节占 10000 元素数组 bigvar

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-06
        • 2014-01-17
        • 2021-08-08
        • 1970-01-01
        • 2013-04-19
        • 1970-01-01
        • 1970-01-01
        • 2019-09-23
        相关资源
        最近更新 更多