【问题标题】:Using free() can't deallocate memory使用 free() 不能释放内存
【发布时间】:2015-07-15 17:11:39
【问题描述】:

函数getFree() 我在一个类似问题的答案中看到了它,但是字符串cpy 在它运行的次数(即T 次)中仍然具有第一次给出的相同字符串。所以,请有人帮忙。

void getFree(char ** ptr) {
    if (*ptr != NULL) {
        free(*ptr);
    }
    return;
}

int main() {
    int T, j;
    scanf("%d", &T);
    for (j = 0; j < T; j++) {
        char * cpy,
        int count = 0, i = 0, x = 0, k = 0;
        cpy = (char*)malloc(500 * sizeof(char));
        if (getchar() == '\n') {
            do {
                *(cpy + i) = getchar();
                i++;
            } while(*(cpy + i - 1) != '\n');
        }
        getFree(&cpy); 
        printf("%s", cpy);           
    }
    return 0;
}

【问题讨论】:

  • 代码到底做了什么你没想到的?你期待什么?
  • 不要在 C 中转换 malloc
  • 对不起,我只是想知道每次for循环运行时如何更改字符串。
  • 你做的 - 它是同一内存中的一个新字符串。不过,您没有将内存归零或终止字符串。也许你可以表现出你不喜欢的特定行为?

标签: c string malloc free


【解决方案1】:

Free 使指针无效,但不改变值。如果这是你想要的,你应该把它归零。释放它之后,它指向的东西是未定义的,但很可能会包含最后的东西,直到它被重用。

free(*ptr);
*ptr = NULL;

【讨论】:

  • 我对这段代码的第一反应是“wtf???”你的反应好多了 - 谢谢!
【解决方案2】:

您可以考虑将您的getFree 设为宏(作为Robert Jacobs' answer 精神的替代方案),例如

#define GET_FREE_AT_BIS(Lin,PtrVar) do { \
  void**ptr_##Lin = (void**) &(PtrVar);  \
  if (*ptr_##Lin) free (*ptr_##Lin);     \
  *ptr_##Lin = NULL;                     \
} while(0)

#define GET_FREE_AT(Lin,PtrVar) GET_FREE_AT_BIS(Lin,PtrVar)
#define GET_FREE(PtrVar) GET_FREE_AT(__LINE__,(PtrVar))

需要双重间接来扩展 __LINE__ 并适用于宏连接。它用于在第 123 行进行宏调用时具有某种独特的变量名称,例如 ptr_123(以简化调试,并经常避免与名为 ptr 的变量发生冲突)

然后编码

GET_FREE(cpy);

没有任何可见的地址运算符(在宏扩展中完成)。

即使以 GET_FREE(ptrarr[i++]); 的形式调用,我的宏也应该可以工作,但它是一个更简单但错误的变体,例如

#define GET_FREE_BUGGY(PtrVar) do { free(PtrVar); PtrVar=NULL; } while(0)

GET_FREE_BUGGY(ptrarr[i++]); 调用时不会像人们期望的那样工作,因为i 会增加两次。

【讨论】:

  • 请注意,if (*ptr_##Lin) 是多余的,free(0) 是静默无操作。除此之外,好主意:)
【解决方案3】:

如果free 没有按照您的建议释放内存,则随后对malloc 的调用将不得不返回不同的地址。请注意,参数没有改变,只是在free 返回后访问它是未定义的行为。

只是因为free 实际上确实释放了内存,所以当您请求相同数量的内存时,对malloc 的后续调用可以(并且确实)返回相同的地址。

为什么不呢?这实际上是最佳行为。如果您只是关心(重新)分配的内存的内容 - freemalloc 都不会告诉您有关其中的内容的任何信息。由于对内容没有任何保证或要求,他们决定不理会它。

如果您希望将内存归零,请改用callocmemset 或其他东西。否则,请放松并停止假设您未初始化的记忆中应该包含什么。

【讨论】:

    【解决方案4】:

    对于您的特定情况,字符串不需要在每次循环迭代中重新分配。考虑一下这个

    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        char * cpy = malloc(500);    // Allocate in the beginning
        int T, i;
        scanf("%d\n", &T);    // Clear newline buffer
        while (T--) {
            // for (i = 0; (cpy[i] = getchar()) != '\n'; ++i);    // Scan until newline
            fgets(cpy, 499, stdin);    // Scan until newline
            printf("%s", cpy);
        }
        free(cpy);    // Free in the end
        return 0;
    }
    

    输入

    3
    abcde
    fghij
    klmno
    

    输出

    abcde
    fghij
    klmno
    

    查看演示 http://ideone.com/KKEz0j

    【讨论】:

      猜你喜欢
      • 2012-05-15
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多