未请求分配的内存
Posted
技术标签:
【中文标题】未请求分配的内存【英文标题】:Memory not requested being allocated 【发布时间】:2015-08-15 13:40:15 【问题描述】:我编写了一个简单的内存分配器,基本上创建了一个分配块链,它们使用存储在分配区域之前的元数据struct
中的指针链接在一起。
代码完美运行,我能够分配大小为sz
的块链,然后使用我编写的另一个函数释放这些块。
问题是我注意到,使用vmmap
命令,显然内存是由malloc
分配的,而没有明确请求它。这是各种vmmap
的粘贴,取自程序执行的不同点:
## before first alloc
# this has been taken before any allocation happens in the code.
REGION TYPE VIRTUAL
=========== =======
Kernel Alloc Once 4K
MALLOC 9388K see MALLOC ZONE table below
MALLOC (admin) 24K
STACK GUARD 56.0M
Stack 8192K
VM_ALLOCATE 8K <-- we start with 8K
__DATA 668K
__LINKEDIT 70.2M
__TEXT 5860K
shared memory 4K
=========== =======
TOTAL 149.8M
VIRTUAL ALLOCATION BYTES
MALLOC ZONE SIZE COUNT ALLOCATED % FULL
=========== ======= ========= ========= ======
DefaultMallocZone_0x10ad37000 9216K 363 27K 0%
=======================================================================
## after first alloc
# this is after the chain allocation.
REGION TYPE VIRTUAL
=========== =======
Kernel Alloc Once 4K
MALLOC 18.2M <-- why the hell does malloc() increase?
MALLOC (admin) 24K
STACK GUARD 56.0M
Stack 8192K
VM_ALLOCATE 8200K <-- this is expected, we allocate memory with vm_allocate()
__DATA 668K
__LINKEDIT 70.2M
__TEXT 5860K
shared memory 4K
=========== =======
TOTAL 166.8M
VIRTUAL ALLOCATION BYTES
MALLOC ZONE SIZE COUNT ALLOCATED % FULL
=========== ======= ========= ========= ======
DefaultMallocZone_0x10ad37000 18.0M 364 31K 0%
=======================================================================
## after chain release
REGION TYPE VIRTUAL
=========== =======
Kernel Alloc Once 4K
MALLOC 19.2M <-- malloc increases even more?!?
MALLOC (admin) 24K
STACK GUARD 56.0M
Stack 8192K
VM_ALLOCATE 8K <-- after chain release
__DATA 668K
__LINKEDIT 70.2M
__TEXT 5860K
shared memory 4K
=========== =======
TOTAL 159.8M <-- but why has total size increased?
VIRTUAL ALLOCATION BYTES
MALLOC ZONE SIZE COUNT ALLOCATED % FULL
=========== ======= ========= ========= ======
DefaultMallocZone_0x10ad37000 19.0M 364 31K 0%
我在 OS X 上,我使用 vm_allocate
例程为我的块分配内存。因此,正如预期的那样,vmmap
中的 VM_ALLOCATE
部分显示在链释放后,部分内存恢复到初始大小,即 8K。我从不在我的代码中调用malloc
。
但显然,MALLOC
部分的大小在分配后会增加!它永远不会释放。总大小,链释放后比链分配前多10MB。
有人知道为什么会发生这种情况吗?我不认为vm_allocate
例程调用malloc
,这是没有意义的。提前感谢您的帮助!
不分配代码的测试
我实际上注释掉了我的程序所做的所有分配代码,基本上留下了一个空的main
函数。然后重复三个vmmap
检查我的程序。结果:
REGION TYPE VIRTUAL
=========== =======
Kernel Alloc Once 4K
MALLOC 9388K see MALLOC ZONE table below
MALLOC (admin) 24K
STACK GUARD 56.0M
Stack 8192K
VM_ALLOCATE 8K
__DATA 668K
__LINKEDIT 70.2M
__TEXT 5860K
shared memory 4K
=========== =======
TOTAL 149.8M
VIRTUAL ALLOCATION BYTES
MALLOC ZONE SIZE COUNT ALLOCATED % FULL
=========== ======= ========= ========= ======
DefaultMallocZone_0x105379000 9216K 363 27K 0%
=========================================================================
REGION TYPE VIRTUAL
=========== =======
Kernel Alloc Once 4K
MALLOC 10.2M see MALLOC ZONE table below
MALLOC (admin) 24K
STACK GUARD 56.0M
Stack 8192K
VM_ALLOCATE 8K
__DATA 668K
__LINKEDIT 70.2M
__TEXT 5860K
shared memory 4K
=========== =======
TOTAL 150.8M
VIRTUAL ALLOCATION BYTES
MALLOC ZONE SIZE COUNT ALLOCATED % FULL
=========== ======= ========= ========= ======
DefaultMallocZone_0x105379000 10.0M 363 27K 0%
=========================================================================
REGION TYPE VIRTUAL
=========== =======
Kernel Alloc Once 4K
MALLOC 11.2M see MALLOC ZONE table below
MALLOC (admin) 24K
STACK GUARD 56.0M
Stack 8192K
VM_ALLOCATE 8K
__DATA 668K
__LINKEDIT 70.2M
__TEXT 5860K
shared memory 4K
=========== =======
TOTAL 151.8M
VIRTUAL ALLOCATION BYTES
MALLOC ZONE SIZE COUNT ALLOCATED % FULL
=========== ======= ========= ========= ======
DefaultMallocZone_0x105379000 11.0M 363 27K 0%
VM_ALLOCATE
区域现在没有增加,正如预期的那样,没有人打电话给vm_allocate
。但是,如您所见,MALLOC
区域仍在增加!即使没有我的代码。它确实比以前增长了更少,即 11MB 而不是 18MB。
这意味着我的代码对其有一些直接影响,但它可能是什么?也许库函数正在调用malloc
?我在分配代码中使用了一些printf
,并且我知道printf
调用malloc
之类的函数,但是为什么没有释放内存?
编辑 - 添加我的代码
很抱歉之前没有包含它,如果一团糟,我很抱歉,我在大约两个小时内写了这篇文章,这是我第一次尝试创建自定义分配器。
#include <mach/mach.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc/malloc.h>
#define BLOCK_NO 2048
typedef struct mem_block
struct mem_block *next;
unsigned int sz;
unsigned int free:1;
mem_block_t;
void *alloc_block(vm_size_t size)
void *block_addr=NULL;
mem_block_t metadata;
vm_address_t *start_addr=0;
vm_allocate(mach_task_self_, (vm_address_t*)&start_addr, size, 1);
block_addr=(start_addr);
metadata.next=(void*)NULL;
metadata.sz=(unsigned int)size;
metadata.free=0x0;
memcpy(block_addr, (mem_block_t*)&metadata, sizeof(mem_block_t));
return block_addr+sizeof(mem_block_t);
void dealloc_block(void *block_addr)
unsigned int sz=0;
vm_address_t start_addr = (vm_address_t)block_addr-sizeof(mem_block_t);
memcpy(&sz, (void*)start_addr+sizeof(mem_block_t*), sizeof(sz));
vm_deallocate(mach_task_self_, start_addr, sz);
void *alloc_block_chain(unsigned int blocks, vm_size_t size)
void *head=NULL, *old_block=NULL, *curr=NULL;
head = alloc_block(size);
old_block = head;
for (int i=0; i<blocks-1; i++)
curr = alloc_block(size);
((mem_block_t*)old_block)->next=curr;
old_block=curr;
return head;
void dealloc_block_chain(void *block_addr_start)
int cnt=0;
void *curr=NULL, *old_block=NULL;
curr=block_addr_start;
while(1)
if (old_block)
dealloc_block(old_block);
malloc_printf("dealloc'd block #%d: %p\n", cnt, old_block);
cnt++;
if (!((mem_block_t*)curr)->next)
dealloc_block(curr);
malloc_printf("dealloc'd final block: %p\n", curr);
break;
else
old_block = curr;
curr=((mem_block_t*)curr)->next;
int main(int argc, const char * argv[])
system("read -n 1 -s -p \"Press any key to continue...\";echo");
void *start = alloc_block_chain(BLOCK_NO, PAGE_SIZE);
void *curr=start;
for (int i=0; i<BLOCK_NO; i++)
malloc_printf("block #%d: %p\n", i, curr);
curr = ((mem_block_t*)curr)->next;
system("read -n 1 -s -p \"Press any key to continue...\";echo");
dealloc_block_chain(start);
system("read -n 1 -s -p \"Press any key to continue...\";echo");
return 0;
可能的解决方案
你可以看到我在代码中使用了malloc_printf
。我之前在那里打电话给printf
。 malloc_printf
函数类似于printf
,但避免调用malloc
。
这似乎修复了泄漏!稍后我会进行更多测试,但就我所见,问题确实可能是printf
的 OS X 实现。
【问题讨论】:
"我知道像printf
这样的函数调用malloc
"...你怎么知道的?
我曾使用过函数挂钩/插入,并多次注意到printf
实现调用malloc
。至少,在 OS X 上!
啊,是的,它可以用于多字节/宽字符串转换。
@KerrekSB 比打开像 VS2015 之前的文件 printf
在 MSVC 上所做的那样好
block_addr+sizeof(mem_block_t)
是什么?这甚至可以编译???
【参考方案1】:
vm_deallocate
函数在指定任务的地址空间中释放虚拟内存区域。该区域从包含地址的虚拟页面的开头开始,到包含address + size - 1
的虚拟页面的末尾结束。由于这种对虚拟页面边界的舍入,释放的内存量可能大于大小。
我认为引用不会被清除,这就是为什么其他线程仍然可以引用这个地址空间的原因。如果你连续运行提到的程序可能会导致崩溃,并且引用也应该被清除。
如果我错了,请纠正我。
【讨论】:
以上是关于未请求分配的内存的主要内容,如果未能解决你的问题,请参考以下文章