【问题标题】:Determining when functions allocate memory in C++确定函数何时在 C++ 中分配内存
【发布时间】:2013-08-09 20:10:13
【问题描述】:

所以我遇到的一个主要问题是确定 C/C++ 中的给定函数是否进行内存分配。我经常使用外部库,其中一些具有返回指向新对象的指针的函数。是否有一些基本的设计范例或约定可以让我提前知道是否分配了内存?

似乎任何返回指向新对象的指针的函数都必须分配内存,但似乎并非总是如此。例如,fopen 没有

编辑:需要明确的是,我无权访问源代码,所以我不能只检查它是使用 new 还是 malloc 等。

【问题讨论】:

  • 大多数库都有删除它们创建的对象的功能。我不确定你提出问题的动机。您可以使用 valgrind 查找内存泄漏。
  • 没有可移植的方法来确定指针是从newmalloc 还是自动存储中获得的。如果库没有记录谁负责释放内存,那么它就是垃圾。

标签: c++ c memory memory-leaks


【解决方案1】:

阅读您使用的所有库的文档。他们应该告诉你是否应该释放某些东西。

【讨论】:

  • 一些库没有很好的文档
  • 那么我建议在一个小测试程序中使用库函数而不释放内存,然后使用 valgrind 查看是否有任何内存泄漏。如果是这样,那么你需要在你的实际程序中释放它。
  • @SamBryant - 不要使用文档记录不佳的库。如果您不知道自己的组件在做什么,就无法设计出好的软件。
【解决方案2】:

如果他们很好地记录了库(就像所有内置库一样),那么它应该在后置条件中说明“调用者必须释放”的内容,函数的子部分副作用。

【讨论】:

    【解决方案3】:

    对于 C++,任何调用 new 或 new [] 的东西都会分配内存。因此,如果一个函数调用那些或调用任何调用 new 的函数(调用任何函数....等等),它就会执行此操作。

    除了调用是 malloc、calloc 和 family 之外,在 C 中相同。

    【讨论】:

    • 是的,我知道,但由于这些是外部库,我通常无权访问源代码,有时它们没有很好的文档
    • 你可以使用像 valgrind 这样的工具或头文件来替换 new 和 delete 并获取它来枚举所有内存分配和空闲调用。
    • @DavidElliman:看起来您既没有正确理解问题,也没有正确理解答案中的 cmets。
    【解决方案4】:

    当然,最好的或至少最简单的解决方案是文档。

    但是,如果您想确保该函数不使用 malloc,您可以包装 malloc(以及它的朋友 calloc、realloc 和最终 free)以收集一些统计信息。

    编写包装器非常简单,至少如果可以使用 dlsym(3)(抱歉,我不知道 windows 的方式),这里是 malloc 的代码:

    void *malloc(size_t s) {
      // Retrieve the pointer to the libc's malloc
      // I use a static var to avoid time penality
      static void* (*real_malloc)(size_t) = NULL;
      if (!real_malloc) real_malloc = dlsym(RTLD_NEXT,"malloc");
      stat.nmalloc += 1; // count malloc calls
      stat.smalloc += s; // count malloced size
      // You can also directly print malloc's parameters
      // but you first need to check that stdio functions
      // doesn't use malloc, or write your own printer
      return real_malloc(s);
    }
    

    在我的示例中,我使用静态全局结构来存储每个函数的调用次数和每次调用的大小总和。包装器代码位于一个小库中,您可以将其与测试代码链接(或者,如果您直接打印统计信息,则可以使用 LD_PRELOAD。)

    结果很有意思,比如你说fopen不使用malloc,用那种技巧,你可以看出是假的。例如,在最近的 64 位 linux 系统上,我在使用 fopen 时收到了一个 568 字节的 malloc 调用([编辑]当然,free 是在 fclose 中完成的。)

    【讨论】:

    • GNU libc 已经内置了 malloc/realloc/free/etc 的钩子,因此您不必手动操作。它还通过mtrace()提供了内置的分配调试器。
    猜你喜欢
    • 1970-01-01
    • 2012-06-02
    • 2022-11-22
    • 2023-03-21
    • 2011-03-15
    • 2016-06-21
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多