【问题标题】:Replacing strings on the heap with new ones用新字符串替换堆上的字符串
【发布时间】:2015-10-14 02:02:32
【问题描述】:

我觉得使用动态类型语言已经破坏了我对此的直觉!

假设我 malloc 为一个字符串留出空间,然后用另一个 malloc 更新该指针(它使用第一个数据),这是内存泄漏吗?

char* my_string = (char*)malloc(length + 1);
(void)snprintf(my_string, length, "blah...");

my_string = some_manipulation(my_string);

我们有 char* some_manipulation(const char* str); 为其输出分配内存,这是从提供的参数生成的(并且可能长度不同)。

第一个malloc 现在是否丢失,但占用空间,直到退出?

【问题讨论】:

    标签: c memory-leaks malloc dynamic-memory-allocation


    【解决方案1】:

    假设我 malloc 为一个字符串留出空间,然后用另一个 malloc 更新该指针(它使用第一个数据),这是内存泄漏吗?

    是的,如果您不存储string 的第一个值,则在第二次调用malloc() 之前将其覆盖。

    代码泄露

    char * p = malloc(42);   
    p = malloc(41);
    
    /* here the program leaks 42 bytes. */
    

    你只能free()第二次调用的41个字节

    free(p);
    

    因为对 42 字节块的引用丢失了。

    不泄露代码

    char * p = malloc(42);
    char * q = p;
    p = malloc(41);
    

    在这里你没有泄漏,你仍然可以这样做:

    free(p); /* Frees 41 bytes. */
    free(q); /* Frees 42 bytes */
    

    它使用第一个数据

    所有这些都完全不依赖于已存储的内容(或不存储)在分配的内存中。

    【讨论】:

      【解决方案2】:

      如果你有两个malloc 调用和一个free 在同一个指针上,你几乎可以肯定有泄漏(没有第一个 malloc 失败)。

      每个成功的malloc 都应该在指针生命周期结束时的某个地方有一个关联的free

      泄漏:

      foo* bar = NULL;
      bar = malloc(sizeof(foo) * 10);
      if (bar) {
          bar = malloc(sizeof(foo) * 20);
      }
      else {
          fprintf(stderr, "Error: Could not allocate memory to bar\n");
          exit(EXIT_FAILURE);
      }
      free(bar);
      bar = NULL;
      

      没有泄漏:

      foo* bar = NULL;
      bar = malloc(sizeof(foo) * 10);
      if (bar) {
          free(bar);
          bar = NULL;
      }
      else {
          fprintf(stderr, "Error: Could not allocate memory to bar\n");
          exit(EXIT_FAILURE);
      }
      bar = malloc(sizeof(foo) * 20);
      if (bar) {
          free(bar);
          bar = NULL;
      }
      else {
          fprintf(stderr, "Error: Could not allocate memory to bar\n");
          exit(EXIT_FAILURE);
      }
      

      【讨论】:

        【解决方案3】:

        是的,当然。您似乎在这里将您的字符串视为一个 不可变对象,这是一个不错的概念,但不会利用您释放占用的内存。

        如果您知道对您的函数的调用在概念上会使输入字符串无效(因此,调用者在调用该函数后将不再需要它),您可以改为执行以下操作:

        int some_manipulation(char **str)
        {
            char *ret = malloc(...);
            /* handle error, return -1 */
            /* do whatever manipulation */
            free(*str);
            *str = ret;
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-14
          • 2017-09-04
          • 1970-01-01
          • 2017-03-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多