26

这似乎是一个非常基本的问题,但它一直在我的脑海中:

当我们分配一个局部变量时,它会进入堆栈。类似地,动态分配会导致变量进入堆。现在,我的问题是,这个变量实际上是位于堆栈还是堆上,或者我们只是堆栈和堆中的一个引用。

例如,

假设我声明了一个变量int i。现在这i是在堆栈上分配的。那么,当我打印 的地址时i,这将是堆栈上的位置之一吗?堆也是同样的问题。

4

6 回答 6

76

我不完全确定你在问什么,但我会尽力回答。

下面i在栈上声明一个变量:

int i;

当我使用请求地址时,&i我得到了堆栈上的实际位置。

当我使用 动态分配某些东西时malloc,实际上存储了两条数据。动态内存是在堆上分配的,而指针本身是在栈上分配的。所以在这段代码中:

int* j = malloc(sizeof(int));

这是在堆上为整数分配空间。它还在堆栈上为指针 ( j) 分配空间。变量j的值设置为返回的地址malloc

于 2011-07-21T02:16:29.160 回答
15

希望以下内容对您有所帮助:

void foo()
{
    // an integer stored on the stack
    int a_stack_integer; 

    // a pointer to integer data, the pointer itself is stored on the stack
    int *a_stack_pointer; 

    // make a_stack_pointer "point" to integer data that's allocated on the heap
    a_stack_pointer = (int*)malloc(10 * sizeof(int));
}

在堆栈变量的情况下,变量本身(实际数据)存储在堆栈中。

在堆分配内存的情况下,底层数据始终存储在堆上。指向该内存/数据的指针可以本地存储在堆栈上。

希望这可以帮助。

于 2011-07-21T02:19:45.653 回答
6

指针变量本身将驻留在堆栈上。指针指向的内存将驻留在堆上。

int *i = malloc(sizeof(int));

i将驻留在堆栈上,我指向的实际内存*i将在堆上。

于 2011-07-21T02:17:19.587 回答
2

我同意克里斯。只是另一种解释方式。考虑以下代码:

int* j = malloc(sizeof(int));
free(j);

即使在使用 free(j) 应该从堆中释放内存之后,指针仍然存在,我们需要明确地将其设为 NULL。这肯定表明指针还有一个堆栈对应物,否则它应该在 free 命令之后不存在。这个堆栈变量是指向堆上使用 malloc 动态分配内存的地址的变量。

于 2013-06-03T10:08:05.240 回答
1

Eberle 先生的回答是 100% 正确的,但是由于 Google 在搜索 时将其显示为第一个答案malloc heap or stack,因此我必须补充一点,它malloc()“大部分”时间都在堆上分配数据。如果分配的数据大于MMAP_THRESHOLD32 位系统上通常的 128kb,malloc()不会使用堆,而是将数据分配到通常位于堆栈下方的匿名内存段中,向低内存方向增长。

这与动态加载的库所在的区域相同(libc.so等)。这是来自的相关段落man malloc

通常,malloc() 从堆中分配内存,并根据需要调整堆的大小,使用 sbrk(2)。当分配大于 MMAP_THRESHOLD 字节的内存块时,glibc malloc() 实现使用 mmap(2) 将内存分配为私有匿名映射。MMAP_THRESHOLD 默认为 128 kB,但可以使用 mallopt(3) 进行调整。在 Linux 4.7 之前,使用 mmap(2) 执行的分配不受 RLIMIT_DATA 资源限制的影响;自 Linux 4.7 起,此限制也适用于使用 mmap(2) 执行的分配。

作为一个实际示例,请随时查看以下帖子。它基本上分配了 300kb,malloc()然后运行pmap <PID>以显示相关的内存段。

于 2018-08-25T09:23:46.040 回答
0

堆栈或堆不是单独的内存,它们是系统为正在运行的程序分配的内存段,只是在内存中组织数据的不同方式。

所以当你得到 &i 时,它就是一个内存地址,就这么简单。

于 2011-07-21T02:19:13.467 回答