堆栈或堆中C ++中的全局内存管理?


72

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

例如

struct AAA
{

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

1
此外,全局变量和静态变量(在函数内)之间有什么区别?他们必须为程序的生命而活...
user128026

同意但他们之间的可访问性有所不同
sameer karjatkar 09年

@dspinozzi:全局变量的构造函数在main()之前调用,但是静态变量的构造函数在首次调用该函数时被调用。两种类型的变量通常都存储在内存的同一部分中-我认为GCC会将它们放在.data节中。
尼尔,2009年

Answers:


138

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

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

  1. 代码-文本段
  2. 初始化数据–数据段
  3. 未初始化的数据– bss段
  4. 叠放

如果您真的想了解保存在何处的内容,请阅读并添加以下标签:

编译器,汇编器,链接器和装载器:一个简短的故事(请参阅表w.5)

内存中程序的剖析

替代文字


这是否意味着未初始化的数据-bss和已初始化的数据是堆的一部分?
sameer karjatkar,2009年

不,它们不是堆的一部分,它们位于我的答复中所写的不同区域(5个不同区域)。堆和堆栈占用了文本和数据段上方的虚拟内存。
米兰,

8
重要的一点是,在程序首次加载到内存时会分配bss和data段,并且它们的大小在运行时不会改变。相比之下,随着执行动态内存操作,堆的内容是易变的,并且在整个运行过程中都在变化。
夸克

3
我认为让堆栈向下增长并让堆向上增长的想法是,以便他们可以按任何比例使用可用内存。但是,不是通过在两者之间加载动态库来防止这种情况吗?
danijar

初始化指向NULL的指针是否会进入data或bss段?route_t* tblhead = NULL;
philx_x

29

这里的问题是问题。假设您有一个很小的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. 这既不在堆的堆栈NOR上分配,也没有分配。相反,它被分配为静态数据,并在大多数现代计算机上放入其自己的内存段中。实际的字符串也被分配为静态数据,并放在思想正确的机器中的只读段中。
  2. 只是一个静态分配的指针;静态数据中一个地址的空间。
  3. 堆栈上分配了指针,main返回时将有效释放该指针。由于字符串是常量,因此它与其他字符串一起分配在静态数据空间中。
  4. 实际上分配的方式与2完全相同。 static关键字告诉您不要在堆栈上分配它。
  5. ...但是buf1在堆栈上,并且
  6. ...已分配的缓冲区空间在堆上。
  7. 顺便说一句,孩子们不要在家尝试这个。 malloc具有感兴趣的返回值;您应该始终检查返回值。

例如:

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

分配的缓冲区空间与全局变量无关。只有指针是全局的。请不要进一步混淆人们。
EFraim

9
哦,别傻了。发问者显然不清楚去哪里,所以我写了一个答案,目的是增进他的理解。
查理·马丁


6

都不行 它是.data节。


这取决于全局内存是由应用程序内联分配还是由应用程序动态分配的
Philippe Leybaert,2009年

1
如果内存是动态分配的,则它不是全局的(就全局变量而言)
EFraim

那么,如果它不在所有程序的范围内,那么它在什么意义上是全局的?
EFraim

2
@Philippe-关键是不能将全局指针指向的数据视为全局数据。它甚至可以在程序执行过程中更改(不同的函数可能会将全局指针重置为所需的任何位置)
EFraim,2009年

1
@Philippe:.data部分也不只是.EXE。
EFraim 2011年

5

全局内存根据应用程序的分配方式预先分配在固定内存块或堆中:

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 Johe

@Don:否。全局对象是指针,而不是它指向的内存。您可以按照自己的方式处理内存。两者都无法持久运行。您有时甚至可以将其指向堆栈。
EFraim

1
如果要从中吸取教训,那就是应该避免在不清楚问题确切含义的地方回答问题。我的回答没错,只是有些人认为他们对单词的解释足以否决所有不支持其观点的事物。即使是现在,在提出问题10个小时后,仍然不清楚OP的含义。
菲利普·莱伯特

是的,这是我提出这个问题的错误。我现在已对其进行编辑
相同karjatkar,2009年

5

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

程序存储空间


0

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

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

这取决于全局对象的确切性质,是指针还是全局对象本身。


-1

全局变量存在于堆中。这是一个特例,因为它们在程序的生命周期中一直存在


-3

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


全局内存永远不会在堆栈上分配。该堆栈仅用于局部变量和参数
Philippe Leybaert 2009年

函数返回时,堆栈变量将“销毁”
user128026 '23
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.