将堆内存设置为空闲状态并不像在C中那样有效

将堆内存设置为空闲状态并不像在C中那样有效,c,memory-management,free,C,Memory Management,Free,我有这个代码片段来理解C中的内存管理函数void free(void*)。我所知道的free函数是它将释放由指针管理的内存。我想看看一块内存被释放后会发生什么,以及该内存块是否仍然可以访问关联的指针 #include <stdio.h> #include <stdlib.h> #include <string.h> #define STR_SIZE 20 int main(int argc, char *argv[]) { char origina

我有这个代码片段来理解C中的内存管理函数
void free(void*)
。我所知道的
free
函数是它将释放由指针管理的内存。我想看看一块内存被释放后会发生什么,以及该内存块是否仍然可以访问关联的指针

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

#define STR_SIZE 20

int main(int argc, char *argv[])
{
    char originalChar [] = "123456789";
    char *myChar = (char*) malloc(sizeof(char) * STR_SIZE);
    if (!myChar) {
        printf("allocation failed!");

        exit(1);
    }
    char *isOk = strncpy(myChar, originalChar, STR_SIZE*sizeof(char));
    if(!isOk) exit(1);

    char *myCharCopy = myChar;
    printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
    printf("The strings = %s\n", myChar);
    printf("The strings = %s\n", myCharCopy);
    free(myChar);
    printf("----- free happened here -----\n");
    // myChar = NULL;
    printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
    printf("The strings = %s\n", myChar);
    printf("The strings = %s\n", myCharCopy);

    return 0;
}

这个结果对我来说意义不大。因为
free
函数应该设置释放内存块,但它不是结果。这里究竟发生了什么事?此外,与堆上内存相关联的指针似乎仍然可以被释放的内存访问。为什么会发生这种情况?根据
C11
标准第§7.22.3.3章的
free
功能

free
函数使
ptr
指向的空间被释放,即生成 可供进一步分配。[..]

它并不要求将指针设置为NULL(或任何其他值)
free()
-ing只是向操作系统表明,可以在需要时回收和重新发布分配的内存

访问
空闲()。因此,一旦调用了
free()
,您就不应该再访问指针了

正是由于这个原因,通常认为在调用
free()
之后立即将
free()
-d指针设置为NULL是一种好的做法,以避免对已释放内存的任何意外访问


也就是说

 printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
还调用
%d
是打印
int
,而不是指针(或字符串)。如果要打印地址,您可能需要使用

 printf("oC = %p, mCC = %p; mC = %p\n", (void*)originalChar, (void*)myCharCopy, (void*)myChar);

根据
C11
标准第§7.22.3.3章的规定,
免费
功能

free
函数使
ptr
指向的空间被释放,即生成 可供进一步分配。[..]

它并不要求将指针设置为NULL(或任何其他值)
free()
-ing只是向操作系统表明,可以在需要时回收和重新发布分配的内存

访问
空闲()。因此,一旦调用了
free()
,您就不应该再访问指针了

正是由于这个原因,通常认为在调用
free()
之后立即将
free()
-d指针设置为NULL是一种好的做法,以避免对已释放内存的任何意外访问


也就是说

 printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
还调用
%d
是打印
int
,而不是指针(或字符串)。如果要打印地址,您可能需要使用

 printf("oC = %p, mCC = %p; mC = %p\n", (void*)originalChar, (void*)myCharCopy, (void*)myChar);
根据:

7.22.3.3
免费
功能

free
功能使
ptr
指向的空间 已解除分配,即可供进一步分配。如果
ptr
是空指针,不会发生任何操作。否则,如果参数 与内存管理函数先前返回的指针不匹配, 或者,如果通过调用
free
realloc
释放了空间,则行为未定义

但是现在您的代码再次按照C标准访问调用未定义行为的内存:

J.2未定义的行为

1在以下情况下,该行为未定义:

指针的值,该指针引用通过调用释放的空间 使用
free
realloc
功能(7.22.3)

包括看起来“工作”。根据:

7.22.3.3
免费
功能

free
功能使
ptr
指向的空间 已解除分配,即可供进一步分配。如果
ptr
是空指针,不会发生任何操作。否则,如果参数 与内存管理函数先前返回的指针不匹配, 或者,如果通过调用
free
realloc
释放了空间,则行为未定义

但是现在您的代码再次按照C标准访问调用未定义行为的内存:

J.2未定义的行为

1在以下情况下,该行为未定义:

指针的值,该指针引用通过调用释放的空间 使用
free
realloc
功能(7.22.3)


包括显示为“工作”。

C不支持OOP。因此,没有托管指针等,也没有调用未定义行为获得的信息。不要在C中使用
malloc
&friends的结果。无意冒犯,但善意的建议:在尝试利用UB之前,您应该正确掌握基本知识。谢谢。我刚刚看到有人做了
(char*)malloc(…)
,我不知道这是不是一个错误@奥拉夫。它是C++中需要的,但是在C中应该避免使用(参见@ SuravgHoHS的评论)。另外,
sizeof(char)
被定义为产生
1
使用它是毫无意义的。C不支持OOP。因此,没有托管指针等,也没有调用未定义行为获得的信息。不要在C中使用
malloc
&friends的结果。无意冒犯,但善意的建议:在尝试利用UB之前,您应该正确掌握基本知识。谢谢。我刚刚看到有人做了
(char*)malloc(…)
,我不知道这是不是一个错误@奥拉夫。它是C++中需要的,但在C中应该避免(SE)。