更新C库,导致堆损坏

时间:2012-01-20 22:58:28

标签: c memory memory-management malloc free

这是一个廉价的黑客,但我正在尝试更改我正在处理的C库的分配方法。出于某种原因,它使用了GlobalLock,可能是因为它曾经是多个DLL。我已将其更改为alloc:

HANDLE BmiDibAlloc(size_t uBytes)
{   
    HANDLE alloc = malloc(uBytes + sizeof (size_t));

    if (alloc != NULL) 
    {
        memcpy_s(alloc, sizeof (alloc), &uBytes, sizeof (size_t));
    }

    return BmiDibAttach(alloc); //just tracks the number of memory allocs for logging
}

BOOL BmiDibFree(HANDLE hdib)
{
    if (!hdib) {
        return TRUE;
    }
    free(hdib);
    // Forget this handle:
    return BmiDibDetach(hdib);
}

由于我不能再使用GlobalSize了,我在第一个sizeof(size_t)字节上调整了分配的大小......

当使用第一种方法分配后位图写入正常时 - 但是,当我转到Free时会引发堆损坏。当然,它可能介于这些调用之间,是否有人通过给出的信息看到了错误?

2 个答案:

答案 0 :(得分:2)

分配块时,分配更多空间,将标头存储在块的开头,然后返回指向块内偏移量的指针(不是块的开头)。例如“return alloc + sizeof(MY_HEADER)”。

当你释放一个区块时,你必须反过来。例如:

BOOL BmiDibFree(HANDLE callerPointer)
{
    actualPointer = callerPointer - sizeof(MY_HEADER);
    free(actualPointer);

注1:为了提高性能,你应该确保“sizeof(MY_HEADER)”是“malloc()”提供的最小对齐的倍数;所以你不会给调用者造成错位问题。

注意2:您可以在块的实际开始处和块的实际末尾添加“canaries”(幻数),并检查这些(在free和realloc期间)以增加检测堆损坏的机会。我这样做并设置了“heap was corrupted”标志,并在任何malloc / free / realloc之前测试此标志(如果堆已损坏,所有后续操作立即失败以避免使混乱变大)。

注3:您可以使用条件编译(例如“#ifdef DEBUGGING”)来启用/禁用包装器的各种功能。我这样做 - 一个用于启用额外检查(金丝雀),一个用于启用统计信息的收集/报告(分配的块总数,最大分配的块数,分配的总字节数,最大数量任何时候分配的字节数。)

答案 1 :(得分:0)

问:你的意思是" sizeof(size_t)"?这通常只有4个字节。与" sizeof(alloc)"相同 - 它可能只是" 4"。