我想了解更多关于堆上发生的事情。所以我看看下面的C代码。它基本上只是在堆上为两个变量分配内存:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
char *char_ptr;
int *int_ptr;
int mem_size;
if(argc < 2)
mem_size = 50;
else
mem_size = atoi(argv[1]);
printf("\t[+] allocating %d bytes of memory on the heap for char_ptr\n", mem_size);
char_ptr = (char *) malloc(mem_size);
if(char_ptr == NULL)
{
fprintf(stderr, "Error: could not allocate heap memory. \n");
exit(-1);
}
strcpy(char_ptr, "This is memory located on the heap.");
printf("char_ptr (%p) --> '%s'\n", char_ptr, char_ptr);
printf("\t[+] allocating 12 bytes of memory on the heap for int_ptr\n");
int_ptr = (int * ) malloc(12);
if(int_ptr == NULL)
{
fprintf(stderr, "Error: could not allocate heap memory.");
exit(-1);
}
*int_ptr = 31337;
printf("int_ptr (%p) --> %d\n", int_ptr, *int_ptr);
printf("\t[-] freeing char_ptr's heap memory...\n");
free(char_ptr);
printf("\t[+] allocating another 15 bytes for char_ptr\n");
char_ptr = (char *) malloc(15);
if(char_ptr == NULL)
{
fprintf(stderr,"Error: could not allocate heap memory.\n");
exit(-1);
}
strcpy(char_ptr, "new memory");
printf("char_ptr (%p) --> '%s'\n", char_ptr, char_ptr);
free(int_ptr);
free(char_ptr);
}
此代码的输出如下所示:
[+] allocating 50 bytes of memory on the heap for char_ptr
char_ptr (0x8827008) --> 'This is memory located on the heap.'
[+] allocating 12 bytes of memory on the heap for int_ptr
int_ptr (0x8827040) --> 31337
[-] freeing char_ptr's heap memory...
[+] allocating another 15 bytes for char_ptr
char_ptr (0x8827050) --> 'new memory'
所以我猜猜char_ptr指向已分配内存的开头( 0x8827008 ),对吗?
由于分配了50个字节,因此该存储器的末尾应指向地址0x882702A。下一个内存分配从地址 0x8827040 开始。我的问题是:为什么int_ptr不指向 0x882702B (第一次内存分配后的下一个地址)?或者换句话说: 0x772702A 和 0x8827040 之间内存发生了什么?
答案 0 :(得分:3)
具体取决于您的C库(依赖于您的操作系统)。导致这种现象的原因有两个:
结果,以... 2A结尾的块被填充到... 30,然后添加16个字节的malloc头,并且你的下一个块从......开始。
答案 1 :(得分:2)
malloc()
不必在下一个内存地址分配。以下是一些原因:
malloc()
仅保证返回一些已分配的内存。它的工作原理是malloc()
- 从界面定义的角度来看,它是一个黑盒子。弄清楚里面发生的事情可能很有趣,但不是标准的一部分。
malloc()
会将分配与方便的边界对齐(通常是64位平台上的64位边界)。
之前的其他库调用可能会有free()
&#39; d块,因此您可以在一个洞内进行分配 - 即在之前的free()
d块内存中
描述堆的内部数据结构紧接在分配数据结构之前。在一个简单的实现中,它们将是一个链表。
malloc()
从多个地方获取记忆;是的,它使用堆(和brk
/ sbrk
),但对于更大的分配,它将mmap()
与MAP_ANON
一起使用。
所有这些因素都可能导致分配不在下一个内存地址中。
答案 2 :(得分:1)
可能是因为堆的控制信息是内联存储的。
换句话说,每个块可能有一个隐藏的&#39;它之前的部分包含控件信息,如块大小,链接到下一个块,标记以检测损坏等等。
它还可能为您提供比请求更多的内存,例如确保它是十六个字节的倍数(尽管您仍然只允许使用您要求的内容)。
然而,底线是你不能依赖任何一个。对于不同的实现,不同的版本或代码运行的那一天,它可能会发生变化: - )
您可以确定它在标准中的含义 - 它将为您提供NULL或可用地址,可以
答案 3 :(得分:1)
谢谢大家的回答!他们帮了很多忙!我对堆的概念有一个基本的误解。
总结已经说过的话:
不幸的是,我不能给你们任何人投票,因为我没有15点声望。我希望你原谅我; - )