未请求分配的内存

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。我之前在那里打电话给printfmalloc_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 的虚拟页面的末尾结束。由于这种对虚拟页面边界的舍入,释放的内存量可能大于大小。 我认为引用不会被清除,这就是为什么其他线程仍然可以引用这个地址空间的原因。如果你连续运行提到的程序可能会导致崩溃,并且引用也应该被清除。 如果我错了,请纠正我。

【讨论】:

以上是关于未请求分配的内存的主要内容,如果未能解决你的问题,请参考以下文章

Redshift WLM 配置:如何使用未分配的内存?

C ++中未初始化的内存分配

NSMutableRequest 对象主体的分配数据未释放

连续内存分配:内存碎片与分区的动态分配

清华大学操作系统(陈渝,向勇)课程笔记——连续内存分配

SQL Server 2008 R2未使用已分配的内存