设置堆内存空闲不起作用,因为它应该在C中

时间:2016-01-11 20:04:55

标签: 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 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;
}

然后,我从输出中得到了这些结果。

    oC = 1482066590, mCC = 826278544; mC = 826278544
    The strings = 123456789
    The strings = 123456789
    ----- free happened here -----
    oC = 1482066590, mCC = 826278544; mC = 826278544
    The strings = 123456789
    The strings = 123456789

这个结果对我来说没什么意义。因为free函数应该释放内存块,但结果是 NOT 。到底发生了什么?此外,似乎与堆上的内存关联的指针仍然可以被释放的内存访问。为什么会这样,因为它被释放了?

2 个答案:

答案 0 :(得分:3)

根据C11标准,章节§7.22.3.3, free函数

  

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

它并不强制将指针设置为NULL(或其他任何东西)。 free() - 仅仅是操作系统的指示,可以在需要时回收和重新发布已分配的内存。

访问free() - d内存为undefined behavior。因此,一旦调用free(),就不应再访问指针了。

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

那就是说,

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

也会调用undefined behavior%d是打印int,而不是指针(或字符串)。如果您想打印地址,可能需要使用

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

答案 1 :(得分:2)

根据C standard

  

7.22.3.3 free功能

     

...

     

free函数会导致ptr指向的空间   取消分配,即可用于进一步分配。如果ptr   是一个空指针,不会发生任何操作。否则,如果参数确实如此   与先前由内存管理函数返回的指针不匹配,   或者如果通过调用freerealloc释放了空格,则行为未定义。

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

  

J.2未定义的行为

     

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

     

...

     

指向通过调用释放的空间的指针的值   使用freerealloc函数(7.22.3)。

包括出现“工作”。