【问题标题】:malloc() vs. HeapAlloc()malloc() 与 HeapAlloc()
【发布时间】:2012-01-03 16:36:18
【问题描述】:

malloc() 和 HeapAlloc() 有什么区别?据我了解 malloc 从堆中分配内存,就像 HeapAlloc 一样,对吧?

那么有什么区别呢?

谢谢!

【问题讨论】:

    标签: c++ winapi malloc


    【解决方案1】:

    实际上,malloc()(和其他 C 运行时堆函数)依赖于模块,这意味着如果您在一个模块(即 DLL)的代码中调用 malloc(),那么您应该在以下代码中调用 free()相同的模块,否则您可能会遭受一些非常严重的堆损坏(这已经有据可查)。将 HeapAlloc() 与 GetProcessHeap() 一起使用而不是 malloc(),包括重载 new 和 delete 运算符以使用它们,允许您在模块之间传递动态分配的对象,并且不必担心如果内存是在代码中分配的内存损坏一旦指向内存块的指针被传递到外部模块,一个模块并在另一个模块的代码中被释放。

    【讨论】:

    • 最后,这是这里最重要的答案。 malloc() 是可移植的,但是当您需要移动对象并涉及 DLL 时,您需要堆。对于 Windows 开发人员,我建议使用 Heap 并为 Heap 编写自定义 STL 分配器。
    • 异议还有效吗?例如 VC 2013 CRT 将 _crtheap 初始化为 GetProcessHeap(),因此来自不同 DLL 的 malloc/free 应该已经使用相同的 GetProcessHeap()。如果混合“发布”和“调试”CRT,则情况不同。后者为返回的指针添加了一个偏移量,因此实际上由调试版本分配并由发布版本(或反向)释放将使程序崩溃。
    • 希望您提供指向您提到的“有据可查”的链接。
    【解决方案2】:

    你是对的,他们都从堆中分配内存。但也有区别:

    • malloc() 是可移植的,是标准的一部分。
    • HeapAlloc() 不可移植,它是一个 Windows API 函数。

    很有可能,在 Windows 上,malloc 将在 HeapAlloc 之上实现。我希望mallocHeapAlloc 快。

    HeapAllocmalloc 具有更大的灵活性。特别是它允许您指定要从哪个堆分配。这可以满足每个进程的多个堆。

    对于几乎所有编码方案,您将使用malloc 而不是HeapAlloc。虽然由于您标记了您的问题 C++,但我希望您使用 new

    【讨论】:

    • 如果malloc 是在HeapAlloc 之上实现的,它怎么能比HeapAlloc 快?
    • @dan04 因为malloc 可能会实现更多的子分配模式。
    • @drhirsch:“没有经验的开发人员的陷阱”当然; “没有其他目的”,并非如此。您可以将它与每个线程堆一起使用,也可以从可执行的堆中分配内存。
    • 它还有其他用途,例如用于 C 或 C++ 以外的语言。实际上,程序员比使用 C 或 C++ 的人多。
    • @drhirsh:微软在这里所做的与其他平台上发生的没有什么不同; malloc() 很少(曾经?)由操作系统直接提供,而是 C 库根据底层操作系统原语来实现它。在 Win32 上,它是 HeapAlloc();在 unix 上,malloc() 通常用 sbrk() 或 mmap() 来实现。文件也存在类似的情况:C 的 fopen() 是根据 Win32 上的 CreateFile() 或 unix 上的 open() 实现的。这里的 OP 的 qu 真的类似于“fopen() vs open()”或“fopen() vs CreateFile()”。
    【解决方案3】:

    在 Visual C++ 中,函数 malloc() 或运算符 new 最终会调用 HeapAlloc()。如果您调试代码,您会发现函数_heap_alloc_base()(在文件malloc.c 中)正在调用return HeapAlloc(_crtheap, 0, size),其中_crtheap 是使用HeapCreate() 创建的全局堆。

    HeapAlloc() 函数很好地减少了内存开销,每次分配至少有 8 个字节的开销。我见过的最大的是每个分配 15 字节,分配范围从 1 字节到 100,000 字节。较大的块具有较大的开销,但占分配总量的百分比仍然低于有效负载的 2.5%。

    我无法对性能发表评论,因为我没有使用自定义例程对 HeapAlloc() 进行基准测试,但是就使用 HeapAlloc() 的内存开销而言,开销非常低。

    【讨论】:

    • 和HeapAlloc()调用在ntdll.dll、kernel32.dll、kernalebase.dll中实现的RtlHeapAlloc()
    • 我在我的开放地址哈希映射 sourceforge.net/projects/cgenericopenaddresshashmap 中有一个基准,表明 Windows 8 malloc 至少比 Windows 7 快 5 倍。有人建议 here MS CRT malloc 只做wrap HeapAlloc,你确认了吗?
    【解决方案4】:

    malloc 是 C 标准库(以及 C++ 标准库)中的一个函数。

    HeapAlloc 是一个 Windows API 函数。

    后者允许您指定要分配的堆,我想这对于避免在不同线程中序列化分配请求很有用(注意HEAP_NO_SERIALIZE 标志)。

    【讨论】:

      【解决方案5】:

      在多个 DLL 可能来来去去(通过 LoadLibrary/Freelibrary)的系统中,当内存可能在一个 DLL 中分配,但在另一个 DLL 中释放时(请参阅上一个答案),HeapAlloc 和相关函数似乎是最不常见的-成功共享内存的分母。

      线程安全,可能由大量博士高度优化,HeapAlloc 似乎可以在我们使用 malloc/free 的不可共享代码会失败的各种情况下工作。

      我们是一家 C++ 嵌入式商店,因此我们在整个系统中重载了运算符 new/delete,以使用 HeapAlloc(GetProcessHeap()),它可以存根(在目标上)或本地(到 Windows)以实现代码可移植性。

      到目前为止,我们已经绕过了 malloc/free,这似乎是无可争议的 DLL,现在没有任何问题,每个 DLL 负载都有一个新的“堆”。

      【讨论】:

        【解决方案6】:

        另外,可以参考:

        https://msdn.microsoft.com/en-us/library/windows/desktop/aa366705(v=vs.85).aspx

        这表明您可以启用由 WinApi 内存分配器管理的 HEAP 的某些功能,例如“HeapEnableTerminationOnCorruption”。

        据我了解,它提供了一些基本的堆溢出保护,这在安全性方面可能被视为您的应用程序的附加值。

        (例如,我宁愿让我的应用程序崩溃(作为应用程序所有者)而不是执行任意代码)

        另一件事是它可能在开发的早期阶段很有用,因此您可以在投入生产之前发现内存问题。

        【讨论】:

          【解决方案7】:

          malloc 是由编译器特定的 C 运行时库 (CRT) 导出的函数。
          C 运行时库 dll 名称从 Visual Studio 版本更改为版本。

          HeapAlloc 函数由 windows 文件夹中的 kernel32.dll 导出。

          【讨论】:

            【解决方案8】:

            这是 MS 不得不说的:http://msdn.microsoft.com/en-us/library/windows/desktop/aa366533(v=vs.85).aspx

            到目前为止提到的一件事是:“malloc 函数的缺点是依赖于运行时。new 运算符的缺点是依赖于编译器和语言。”

            此外,“如果无法分配内存,可以指示 HeapAlloc 引发异常”

            因此,如果您希望您的程序使用任何 CRT 运行,或者可能根本不使用 CRT,您将使用 HeapAlloc。也许只有会做这种事情的人才是恶意软件编写者。另一种用途可能是,如果您正在编写具有特定内存分配/使用模式的内存密集型应用程序,您宁愿编写自己的堆分配器而不是使用 CRT 分配器。

            【讨论】:

              猜你喜欢
              • 2013-01-16
              • 2016-06-29
              • 2013-01-02
              • 2011-06-03
              • 1970-01-01
              • 2018-08-01
              • 2014-11-12
              • 2011-10-21
              • 2012-07-23
              相关资源
              最近更新 更多