c - 更新 C 库,导致堆损坏

标签 c memory memory-management malloc free

这是一个廉价的 hack,但我正在尝试更改我正在开发的 C 库的分配方法。由于某种原因它使用了 GlobalLock,也许是因为它曾经是多个 DLL。我已将其更改为分配:

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 时,它​​会引发堆损坏。假设它可能位于这些调用之间的某个位置,有没有人发现所提供的信息有问题?

最佳答案

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

当你释放一个 block 时,你必须执行相反的操作。例如:

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

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

注2:您可以在 block 的实际开始处和 block 的实际结束处添加“金丝雀”(魔数(Magic Number)),并检查这些(在 free 和 realloc 期间)以增加检测堆损坏的机会。我这样做并设置一个“堆已损坏”标志,并在任何 malloc/free/realloc 之前测试此标志(如果堆已损坏,所有后续操作都会立即失败,以避免使困惑变得更大)。

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

关于c - 更新 C 库,导致堆损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8948923/

相关文章:

c++ - Valgrind:来自复制构造函数的大小为 8 的无效写入

performance - 异或链表的目的?

macos - 如何在进程启动时降低 IOKit 保留的内存量?

c - 为什么这些常量以不同的方式声明?

c++将函数中的临时分配链接到自定义分配器?

c++ - 如何在 C++ 中初始化列表 vector ?

Python无限期挂起试图删除深度递归对象

c - 如何找到文件系统 ext2 中稀疏文件的大小?

c - 递归函数 C?

python - 将 VBA Type/C 结构移植到 Python ctypes.Structure : array of strings with fixed length