【问题标题】:Memory allocation on Windows C codeWindows C 代码上的内存分配
【发布时间】:2010-09-19 14:49:58
【问题描述】:

我想知道在 Windows C 编程中推荐哪种方法:使用 malloc 或 Win32 HeapAlloc(可能是 VirtualAlloc?)函数。

我已阅读 MSDN Memory Management Functions 文章和有关 malloc 和 HeapAlloc 的 MSDN 文章,但他们没有说明应该使用哪个以及在什么情况下使用。

【问题讨论】:

    标签: c++ c malloc virtualalloc heapalloc


    【解决方案1】:

    除非您有令人信服的理由使用不同的东西,否则请坚持使用 malloc。它将根据操作系统内存分配原语在底层实现,但自己深入到该层并没有真正的优势。

    我认为一些 API 调用需要从 Windows 堆中分配一个内存块,但是当你遇到它们时你就会知道。

    或者如果你想做一些更高级的事情,比如使用共享内存,或者需要直接控制内存页面的权限,那么你需要查看 Windows API 调用,比如 VirtualAlloc。

    【讨论】:

      【解决方案2】:

      如果您确实有大量数据要处理,或者无论如何都需要费心创建自己的内存管理器,VirtualAlloc 和朋友可以为您提供一点优势。

      否则,只使用 malloc() 会更容易,当然也更便携。

      VirtualAlloc 有一个称为 MEM_RESET 的漂亮功能,它使内存块中的数据无效,但保持分配状态。这意味着如果它被分页到磁盘,Windows 将不会在您下次访问它时将其分页。如果您有大量可能突然变得不必要的数据,那就太好了,但是您很快就会有其他东西来填满缓冲区。

      它还区分了保留地址空间和实际请求内存。如果你有充分的理由去解决所有这些麻烦,那里有一些不错的东西。

      【讨论】:

        【解决方案3】:

        还有一件事:malloc() 保证可移植(至少对于任何 ANSI-C 实现而言)并且更优雅。

        【讨论】:

          【解决方案4】:

          在某些情况下使用 HeapAlloc 等函数,HeapFree 会让您的生活更轻松。一个例子是:一个大型应用程序,您需要在一个模块中分配内存(例如在 library1.dll 中)并在主模块中释放该内存(例如 program.exe)。如果您使用 HeapAlloc、HeapResize 和 HeapFree 函数,这可以安全地完成,但不能使用 C 运行时库(例如 malloc、free、resize)完成。

          但是:如果你没有充分的理由,你应该坚持使用 malloc/free/resize 函数。 另外,如果您需要更改分配内存的权限(例如:使 if 可执行等),您应该使用 VirtualAlloc、VirtualFree 等函数。

          【讨论】:

          • 你能解释一下为什么用 malloc() 分配的内存——不管位置——不能被 free() 释放吗?听起来很奇怪!
          • 因为 C 标准对构建过程没有任何规定,它允许实现规定跨 dll 可以做什么和不可以做什么的条件。例如,如果 malloc/free 使用静态变量并且是静态链接的,那么每个 dll 都会有自己的副本。讨厌,但合法。
          • 声明错误:你可以在DLL中malloc,在EXE中free,只要你使用MSVCRT*.DLL。应该是“无法使用 static C 运行时库”
          • 是的,如果您与 msvcrtX.dll 进行动态链接,它应该可以工作。
          【解决方案5】:

          您可以制作一个包装器并保留更改实现细节的选项。您甚至可以将这两个选项与您的代码进行比较,然后再决定。

          【讨论】:

            【解决方案6】:

            与 Rob 不同,我选择了另一种方式...因为我选择针对 WinAPI 进行编码,所以我使用本机函数而不是 C 运行时函数,反正它们只是对它们的一个薄包装。

            【讨论】:

            • 这样做的一个缺点是,如果您尝试将其他一些 C 库合并到您的应用程序中,它可能会期望使用 malloc,现在您必须格外小心使用哪个分配器。
            • 啊,但无论如何,您必须始终使用例程来释放库本身提供的内存(希望作者足够聪明地提供它!),因为您可以拥有静态链接的 DLL一个运行时和你的应用程序依赖于另一个运行时,肯定会崩溃!
            【解决方案7】:

            使用 HeapAlloc,您可以为不同的任务/子系统创建单独的堆。这可能会简化大型应用程序的转储分析。

            使用 malloc,您只能使用一个堆,但您可以获得一些 CRT 作者可能在 OS HeapAlloc 之上实现的分配优化。

            除非您想实现自定义堆管理器(您自己的一组 Heap* 函数),否则使用 VirtualAlloc 并不会为您带来太多好处。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-03-22
              • 1970-01-01
              • 2012-01-16
              • 1970-01-01
              • 2021-02-09
              • 2011-01-05
              • 1970-01-01
              相关资源
              最近更新 更多