【问题标题】:Global memory management in C++ in stack or heap?C++ 中的堆栈或堆中的全局内存管理?
【发布时间】:2010-11-13 06:44:44
【问题描述】:

如果我在 C++ 应用程序中全局声明一个数据结构,它会消耗堆栈内存还是堆内存?

例如

struct AAA
{

.../.../.
../../..
}arr[59652323];

【问题讨论】:

  • 另外,全局变量和静态变量(在函数内)有什么区别。他们必须为节目的生命而活......
  • 同意,但他们在可访问性之间存在差异
  • @dspinozzi:全局变量的构造函数在 main() 之前调用,但静态变量的构造函数在函数第一次调用时被调用。这两种类型的变量通常存储在内存的相同部分——我认为 GCC 将它们放在 .data 部分。

标签: c++ memory-management stack


【解决方案1】:

由于我对答案不满意,并希望同样的 karjatkar 想要学习的不仅仅是简单的是/否答案,所以你去吧。

通常一个进程会分配5个不同的内存区域

  1. 代码 - 文本段
  2. 初始化数据 - 数据段
  3. 未初始化的数据 - bss 段
  4. 堆栈

如果您真的想了解保存的内容,请阅读这些内容并为其添加书签:

COMPILER, ASSEMBLER, LINKER AND LOADER: A BRIEF STORY(见表 w.5)

Anatomy of a Program in Memory

【讨论】:

  • 这是否意味着未初始化的数据 - bss 和已初始化的 - 数据是堆的一部分?
  • 不,它们不是堆的一部分,它们位于我的回答中所写的不同区域(5 个不同区域)。堆和栈占用文本和数据段上方的虚拟内存。
  • 重要的是,bss和data段是在程序第一次加载到内存时分配的,运行时它们的大小不会改变。相比之下,堆的内容是不稳定的,并且在整个运行过程中随着动态内存操作的执行而变化。
  • 我认为让堆栈向下增长并让堆向上增长的想法是让他们可以以任何比例使用可用内存。但是,这不是通过在两者之间加载动态库来防止的吗?
  • 初始化指向 NULL 的指针是否进入数据或 bss 段? route_t* tblhead = NULL;
【解决方案2】:

这里的问题是问题。假设您有一个像这样的小型 C(++,它们以相同的方式处理) 程序:

/* my.c */

char * str = "Your dog has fleas.";  /* 1 */
char * buf0 ;                         /* 2 */

int main(){
    char * str2 = "Don't make fun of my dog." ;  /* 3 */
    static char * str3 = str;         /* 4 */
    char * buf1 ;                     /* 5 */
    buf0 = malloc(BUFSIZ);            /* 6 */
    buf1 = malloc(BUFSIZ);            /* 7 */

    return 0;
}
  1. 这既不是在堆栈上分配,也不是在堆上。相反,它被分配为静态数据,并在大多数现代机器上放入自己的内存段中。实际的 string 也被分配为静态数据并放入正确思考机器中的只读段中。
  2. 只是一个静态分配的指针;一个地址的空间,在静态数据中。
  3. 堆栈上分配了指针,当main返回时将被有效地释放。字符串,因为它是一个常量,所以与其他字符串一起分配在静态数据空间中。
  4. 实际上是在 2 处分配的。static 关键字告诉您它不分配在堆栈上。
  5. ...但是buf1 在堆栈上,并且
  6. ... malloc 的缓冲区空间在堆上。
  7. 顺便说一句,孩子们不要在家里尝试这个。 malloc 有一个感兴趣的返回值;您应该始终检查返回值。

例如:

char * bfr;
if((bfr = malloc(SIZE)) == NULL){
   /* malloc failed OMG */
   exit(-1);
}

【讨论】:

  • 分配的缓冲区空间与全局变量无关。只有指针是全局的。请不要进一步混淆人们。
  • 哦,别傻了。提问者显然不清楚去哪里了,所以我写了一个答案,旨在提高他的理解。
【解决方案3】:

在 C++ 中全局声明数据结构都不会消耗堆或堆栈内存。实际上,全局变量通常分配在一个数据段中,其大小在整个程序期间保持不变。堆栈和堆通常用于在执行程序期间创建和销毁的变量。

【讨论】:

    【解决方案4】:

    全局内存预先分配在固定内存块或堆上,具体取决于应用程序的分配方式:

    byte x[10]; // pre-allocated by the compiler in some fixed memory block
    byte *y
    
    main()
    {
       y = malloc(10); // allocated on the heap
    }
    

    编辑

    这个问题令人困惑:如果我在 C++ 应用程序中全局分配数据结构,它会消耗堆栈内存还是堆内存?

    “分配”?这可能意味着很多事情,包括调用 malloc()。如果问题是“如果我在全球范围内声明和初始化一个数据结构”,情况会有所不同。

    许多年前,当 CPU 仍在使用 64K 段时,一些编译器足够智能,可以从堆中动态分配内存,而不是在 .data 段中保留一个块(由于内存架构的限制)。

    我想我只是太老了......

    【讨论】:

    • 它是“在堆上分配的”,这是非常正确的。除非这个问题被标记为“新手”或“初学者”,否则这应该足以提醒正在发生的事情。
    • @Don:不。全局的东西是指针,而不是它指向的内存。您可以按照自己的方式处理内存。它也不会一直待在那里。有时您甚至可以将其指向堆栈。
    • 如果要从中吸取一个教训,那就是你应该避免回答问题的确切含义不清楚的问题。我的回答没有错,只是有些人认为他们对一个词的解释就足以将不支持他们观点的一切都否决。即使是现在,在提出问题 10 小时后,仍然不清楚 OP 的意思。
    • 是的,这是我提出问题时的错误。我现在编辑了它
    【解决方案5】:

    全局对象本身将占用运行时或编译器在执行 main 之前为其保留的内存,这不是可变的运行时成本,因此既不是堆栈也不是堆。

    如果对象的ctor分配内存,它将在堆中,并且该对象的任何后续分配都将是堆分配。

    这取决于全局对象的确切性质,如果它是一个指针或整个对象本身是全局的。

    【讨论】:

      【解决方案6】:

      全局变量存在于堆上。这些是一个特例,因为它们为程序的生命而存在

      【讨论】:

        【解决方案7】:

        通常两者都不消耗。它尝试将它们分配到一个内存段中,该段可能在程序执行中保持恒定大小。它可能是 bss、堆栈、堆或数据。

        【讨论】:

        • 通过编辑 boot.ini 文件,我们可以将虚拟内存扩展到 3GB 。同样明智的是,内存段是否有任何设置?
        • 那毫无意义,因为静态分配的内存大小永远不会改变
        【解决方案8】:

        如果你自己通过 new 或 malloc 显式分配内存,那么它将在堆中分配。如果编译器正在分配内存,那么它将在堆栈上分配。

        【讨论】:

        • 全局内存永远不会在堆栈上分配。栈只用于局部变量和参数
        • 函数返回时堆栈变量被“销毁”
        【解决方案9】:

        两者都没有。它是 .data 部分。

        【讨论】:

        • 这取决于全局内存是内联分配还是从应用程序动态分配
        • 如果内存是动态分配的,它不是全局的(在全局变量的意义上)
        • 如果不在所有程序的范围内,它在什么意义上是全局的?!
        • @Philippe - 关键是全局指针指向的数据不能被认为是全局的。它甚至可以在程序执行期间发生变化(不同的函数可能会将全局指针重置到他们想要的任何位置)
        • @Philippe:.data 部分也不仅仅是 .EXE。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-10
        • 2014-12-05
        • 2016-06-23
        • 2015-09-28
        • 2011-09-16
        • 1970-01-01
        • 2012-03-07
        相关资源
        最近更新 更多