释放函数内部的指针,并在 main 中使用它

Freeing a pointer inside a function, and using it in main

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

char* test() {
    char* s = "Hello World";
    size_t len = strlen(s);
    char* t = malloc(sizeof(char)*(len+1));
    strcpy(t, s);
    free(t);
    return t;
};

int main(void) {
    printf("%s\n", test());
    return 0;
};

我想在函数内部分配和取消分配内存。我测试了这段代码并且有效,但我想知道:

一旦你在一个指针上调用free,它指向的内存就不再有效。尝试使用指向已释放内存的指针会触发 undefined behavior。在这个 特殊的 案例中,它碰巧起作用了,但不能保证。

如果函数 returns 分配了内存,调用者有责任释放它:

char* test() {
    char* s = "Hello World";
    size_t len = strlen(s);
    char* t = malloc(sizeof(char)*(len+1));
    strcpy(t, s);
    return t;
};

int main(void) {
    char *t = test();
    printf("%s\n", t);
    free(t);
    return 0;
};

malloc 保留内存以供使用。

free 释放该保留。通常,它不会使内存消失,不会更改该内存的内容,也不会更改保存地址的指针的值。

free(t) 之后,t 的字节仍然包含与 free 之前相同的位设置。然后 return t; return 将这些位发送给调用者。

main 将这些位传递给 printf 时,printf 将它们用作地址以获取 %s 的字符。由于没有任何改变,它们被打印出来。

这就是为什么你得到了你对这个程序所做的行为。但是,none 是有保证的。一旦用 t 调用 free,内存预留就消失了。您程序中的其他东西可能使用了该内存。例如,printf 可能已经为其内部使用分配了一个缓冲区,并且可能使用了相同的内存。

在大多数情况下,mallocfree 只是协调使用内存的方法,这样您的程序的不同部分就不会尝试同时使用同一内存不同的目的。当您的程序只有一部分使用分配的内存时,程序的其他部分不会干扰它。所以缺乏协调并没有导致你的程序失败。如果您的程序中有多个例程使用分配的内存,那么在释放内存后尝试使用内存更有可能遇到问题。

此外,一旦内存被释放,编译器可能会将指向它的指针视为没有固定值。 return t; 语句不需要 return 任何特定值。

free() 指向何处并不重要。一旦它是 free()d,指针就不再是可延迟的(既不在函数内部也不在函数外部,它是 free()d)

free() 的目的是 return 用 malloc() 分配的内存,所以语义是,一旦你释放了一块内存,它就不再可用了。

在C中,所有参数都是按值传递的,所以free()不能改变你传递给它的值表达式,这就是指针不会变成无效指针值的原因(比如NULL) 但建议您在不引发未定义行为的情况下不能再使用指针。

free()的设计中可以有一个解决方案,就是把保存指针的指针变量按地址传递,这样free()就可以把指针变成一个NULL。但这不仅需要做更多的工作,而且 free() 不知道你对 malloc() 给你的价值做了多少份......所以不可能知道你有多少引用有在那里作废。这种方法不可能赋予 free() 使对 returned 内存的引用无效的责任。

所以,如果你认为 free 不会将指针变成 NULL 并且出于某些奇怪的原因你仍然可以使用内存 returned,请不要再这样做了,因为你会犯错的。

建议您! :)