试着在C中免费拨打电话

时间:2011-10-03 14:56:22

标签: c memory-management free

编辑看来这只是示例代码错误的一种情况。谢谢你清理这个,SO。

查看http://staff.um.edu.mt/csta1/courses/lectures/csa2060/c8a.html

中的以下代码/引用
//f.c    
#include <stdio.h>
#include <stdlib.h>

char *foo(char *);

main() {
    char *a = NULL;
    char *b = NULL;

    a = foo("Hi there, Chris");
    free(a);

    b = foo("Goodbye");
    free(b); 

    printf("From main: %s %s\n", a, b);
}

char *foo(char *p) {
    char *q = (char *)malloc(strlen(p)+1);
    strcpy(q, p);
    printf("From foo: the string is %s\n", q);    
    return q;
}
  

如果省略free(b),则可以看到“Goodbye”被写入“Hi there,Chris”的位置。

我不明白为什么你必须在printf()语句中使用自由变量之前调用自由(事实上,在我看来,首先释放内存似乎会使其失败)。

道歉,如果这是重复,但搜索/阅读我能找到的东西我仍然在黑暗中。 代码和引用来自此处:http://staff.um.edu.mt/csta1/courses/lectures/csa2060/c8a.html

编辑看来这只是示例代码错误的一种情况。谢谢你清理这个,SO。

5 个答案:

答案 0 :(得分:3)

当您不需要再次使用内存时,请致电free()

在释放两个字符串之后,您的printf()出现,因此当您尝试打印字符串时调用“未定义的行为”(UB)。您a bmain()中的free()printf()都有相同的地址,在这种情况下,您只能在空格中存储两个字符串中的一个,课程。但那仍然是UB,任何事情都可能发生。

您只应在main() #include <stdio.h> #include <stdlib.h> char *foo(char *); int main(void) { char *a = NULL; char *b = NULL; a = foo("Hi there, Chris"); b = foo("Goodbye"); printf("From main: %s %s\n", a, b); free(a); // Now it is safe to free the memory free(b); return 0; } char *foo(char *p) { char *q = (char *)malloc(strlen(p)+1); strcpy(q, p); printf("From foo: the string is %s\n", q); return q; } 之后致电{{1}}。

{{1}}

答案 1 :(得分:2)

当您调用free(a)时,您正在指示运行时释放指针变量a指向的内存。到达printf时,a不再指向有效内存。偶然地,b被分配了a曾经拥有的相同内存。 (然后b也被释放,因此两个指针都无效。)

在两个无效指针处打印字符串是未定义的行为。偶然,内存包含您之前复制的字符串的内容。

答案 2 :(得分:1)

在释放后使用变量是一个错误。在程序中,在调用free()之后打印值,这是错误的。如果它有效,这是偶然的。

通常认为在同一函数中调用malloc()和free()是最佳实践。在您的示例中,这意味着您调用malloc,将生成的缓冲区作为参数传递给foo(),打印结果并免费调用。

答案 3 :(得分:1)

您必须获得如下输出:

From foo: the string is Hi there, Chris
From foo: the string is Goodbye
From main: 

根据您的代码,这是完全合理的,因为您已经释放了将在最后一个printf语句中使用的变量。

我将您的代码修改为:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *foo(char *);

main() {
  char *a = NULL;
  char *b = NULL;

  a = foo("Hi there, Chris");

  b = foo("Goodbye");

  printf("From main: %s %s\n", a, b);
  free(a);
  free(b);
}

char *foo(char *p) {
  char *q = (char *)malloc(strlen(p)+1);
  strcpy(q, p);
  printf("From foo: the string is %s\n", q);
  return q;
}

上述程序的输出是:

From foo: the string is Hi there, Chris
From foo: the string is Goodbye
From main: Hi there, Chris Goodbye

答案 4 :(得分:0)

这在许多层面都是错误的。在foo中,你是为字符串动态分配空间并填充它 - 这很好。

关键是你现在为每个字符串a和b都有一个容器(井,内存块),因为你在两者上都调用了foo。您需要该容器来保存您希望使用它的持续时间。

因此,在完成使用之前,您无法在a或b上免费拨打电话。你过早地调用它(在你的printf()之前),所以你导致了未定义的行为。众所周知,在printf打印内容之前,计算机已经为a和b重用了内存空间。这可能会导致你出现故障或类似的事情。

完成后,在printf之后免费拨打电话。

此外,将指针a和b设置为NULL,这样您就知道它们是空的。在使用/取消引用之前,请务必检查指针是否具有值(非空),并且您将节省很多麻烦。