我正在计算一个块中有多少字节被边界标记占用。有人告诉我,当尝试malloc
一个相邻的内存块时,汇编代码中会出现一个"跳转",我可以用它来确定边界标记的大小。我试过这个:
int* arr = malloc(8);
arr++;
arr = malloc(8);
但汇编代码中没有任何跳跃。我是否在"尝试malloc
一个相邻的内存块"?
EDIT:我认为他的意思是地址值之间会出现跳跃。我使用存储器的第二块的开头减去第一块的有效载荷大小。但我仍然很困惑,我怎么能malloc
一个相邻的内存块?
除非您正在编写一个实际的内存分配器,否则您实际上无法分配两个连续的内存块。如果你想看到一些相当粗糙的代码来实现这一点,可以看看Illumos mallochttps://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/gen/malloc.c.
如果您想了解Illumos(和Solaris)如何处理分配的块之间的红区,您应该浏览https://github.com/illumos/illumos-gate/tree/master/usr/src/lib/libumem/common.
malloc(3)
消耗的内存需要一些结构,这些结构也必须动态分配,才能正确管理实际使用的内存。出于这个原因,许多分配器只分配与专用于用户的块空间相邻的管理数据所需的空间。这使得通常由malloc(2)
分配的两个连续的内存丢弃在它们的地址中显示出一些间隙。
看到差距还有其他原因,其中一个基本原因是malloc通常会为您提供对齐的内存地址,因此您存储在该内存上的数据将正确对齐是有保证的。
当然,也有一些实现(通常情况下,堆分配在缓冲区溢出方面应该更稳健),专用于存储管理数据的内存与最终给定的内存完全无关。在这种情况下,在某些情况下,您可以观察到内存分配之间没有间隙。
不管怎样,你的代码有严重的错误,让我们看看:
int* arr = malloc(8);
在这里,您最好只获取所需的内存,使用sizeof
运算符,而不是int *arr = malloc(sizeof *arr);
。
arr++;
这个语句是无用的,因为您将在malloc()
的值之后用新的赋值语句覆盖arr
(指针)的值,所以增加指针值是没有用的。您也在某种程度上丢失了前一个malloc()
的返回值(这对于返回分配的内存至关重要,但请参阅下文)。
arr = malloc(8);
在此之前,您有机会--arr
递减arr
的值,以便能够执行该块的free(3)
。但是此语句会覆盖存储在arr
中的值,因此新指针会覆盖以前的指针值。您在第一个malloc上获得的内存无法再次访问。这就是通常所说的内存泄漏,通常是长时间运行的程序(如服务器或系统守护进程)上的严重错误(很难捕捉)。程序在循环的内部分配一堆内存,这些内存不会通过调用free(3)
返回,因此程序开始不断增长,直到耗尽所有可用内存。
最后一点,我不明白你对malloc相邻内存块是什么意思。你相信增加指针会使malloc()
给你一个特殊的内存块吗?
- 首先,malloc不知道你将如何处理它给你的指针
- 但是,它对您分配给的指针的变量内容一无所知(您甚至不能将其存储在变量中,并将其作为另一个参数传递给其他函数)。因此,malloc不可能知道您已经从其主体增加了指针值,甚至指针位置
我猜不出你的解释。如果知道是什么让你认为你可以控制malloc(3)
如何选择要给你的内存块,那就太好了。您无法控制malloc()
的内部。您只需指定所需的连续内存量,mallocs就会提供它,为您提供一个指向该块开头的指针。您不能假设下次调用malloc(内存量相同或不同)时,它会给您一个相邻的块。它可以与前一个给定的块完全无关(在内存中的上方或下方)。您不能修改该指针,因为一旦您不再需要块,就需要它来调用free(3)
,并且与malloc(3)
给您的指针值完全相同。如果由于某种原因修改了指针,则需要将其恢复为原始值才能调用free(3)
。如果不这样做,您可能会在下一次调用free(3)
时使程序崩溃。
我刚刚看到内存泄漏。Malloc 2次进入不同的vars 8字节的空间,看看差异是否超过8字节或2 int.