未请求分配的内存

时间:2015-08-15 13:40:16

标签: c memory

我编写了一个简单的内存分配器,基本上创建了一个已分配的块链,它们使用存储在分配区域之前的元数据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例程为我的块分配内存。因此,正如预期的那样,VM_ALLOCATE中的vmmap部分显示链释放后,部分内存返回初始大小,即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实现。

1 个答案:

答案 0 :(得分:1)

vm_deallocate函数在指定任务的地址空间中释放虚拟内存区域。该区域从包含地址的虚拟页面的开头开始,并在包含address + size - 1的虚拟页面的末尾结束。由于这种向虚拟页面边界的舍入,释放的内存量可能大于大小。 我认为引用不会被清除,这就是为什么其他线程仍然可以引用这个地址空间的原因。如果你连续运行上面提到的程序,它可能会导致崩溃,同时还需要清除引用。 如果我错了,请纠正我。