编辑看来这只是示例代码错误的一种情况。谢谢你清理这个,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。
答案 0 :(得分:3)
当您不需要再次使用内存时,请致电free()
。
在释放两个字符串之后,您的printf()
出现,因此当您尝试打印字符串时调用“未定义的行为”(UB)。您a
b
和main()
中的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,这样您就知道它们是空的。在使用/取消引用之前,请务必检查指针是否具有值(非空),并且您将节省很多麻烦。