为什么我们不能在堆栈上分配动态内存?

在堆栈上分配内容非常棒,因为我们拥有RAII,而且不必担心内存泄漏等问题。 但有时我们必须在堆上分配:

  • 如果数据真的很大(推荐) - 因为堆栈很小。

  • 如果要分配的数据大小只在运行时知道(动态分配)。

  • 两个问题:

  • 为什么我们不能在堆栈上分配动态内存(即仅在运行时才知道的内存大小)?

  • 为什么我们只能通过指针指向堆上的内存,而堆栈中的内存可以通过一个普通变量来引用? 即Thing t;

  • 编辑:我知道一些编译器支持可变长度数组 - 这是动态分配堆栈内存。 但这是一般规则的例外。 我有兴趣了解为什么通常我们不能在堆栈上分配动态内存的根本原因 - 它的技术原因和背后的理由。


    为什么我们不能在堆栈上分配动态内存(即仅在运行时才知道的内存大小)?

    实现这一点比较复杂。 由于完成的可执行文件需要包含才能工作的指令类型,每个堆栈帧的大小会被烧入到编译后的程序中。 例如,你的函数局部变量的布局以及其他东西,通过它在底层汇编代码中描述的寄存器和内存地址,被硬编码到程序中:“变量”实际上并不存在于可执行文件中。 为了让这些“变量”的数量和大小在编译运行之间改变,这个过程会大大复杂化,尽管这不是不可能的(正如你发现的那样,使用非标准的可变长度数组)。

    为什么我们只能通过指针来引用堆上的内存,而堆栈中的内存可以通过一个普通变量来引用

    这只是语法的结果。 C ++的“正常”变量恰好是具有自动或静态存储持续时间的变量。 语言的设计者可以在技术上取得了它,这样你可以写类似Thing t = new Thing ,只是用一个t了一整天,但他们没有; 再次,这将会更难实施。 那么如何区分不同类型的对象呢? 请记住,你编译的可执行文件必须记住自动销毁一种而不是另一种。

    我很想详细说明为什么这些事情不是很困难,因为我相信这就是你在这之后所做的。 不幸的是,我对装配的知识太有限了。


    为什么我们不能在堆栈上分配动态内存(即仅在运行时才知道的内存大小)?

    从技术上讲,这是可能的。 但未经C ++标准认可。 可变长度数组(VLA)允许您在堆栈内存上创建动态大小的构造。 大多数编译器允许将其作为编译器扩展。

    例:

    int array[n];
    
    //where n is only known at run-time
    

    为什么我们只能通过指针指向堆上的内存,而堆栈中的内存可以通过一个普通变量来引用? Thing t;

    我们可以。 无论您是否执行,都取决于手头特定任务的实施细节。

    例:

    int i;
    int *ptr = &i;
    

    我们可以使用函数_alloca在堆栈内存上动态分配可变长度空间。 该函数从程序堆栈分配内存。 它只需要分配几个字节,并将void *作为malloc调用返回到分配的空间。 这个分配的内存将在函数退出时自动释放。

    所以不需要明确地解放。 在这里必须记住分配大小,因为可能会发生堆栈溢出异常。 堆栈溢出异常处理可用于此类调用。 如果发生堆栈溢出异常,可以使用_resetstkoflw()将其还原。

    所以我们使用_alloca的新代码将是:

     int NewFunctionA()
     {
      char* pszLineBuffer = (char*) _alloca(1024*sizeof(char));
      …..
      // Program logic
       ….
     //no need to free szLineBuffer
     return 1;
    }
    
    链接地址: http://www.djcxy.com/p/79831.html

    上一篇: Why can't we allocate dynamic memory on the stack?

    下一篇: Is there any limit on stack memory?