理解指向malloc和free的指针

Mih*_*aru 6 c arrays malloc free pointers

指针在C中是一个非常棘手的事情.因为很多人很难理解它,所以为了更好地理解我写了下面的代码:

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

int main(int argc, char *argv[])
{
    int *p; // pointer -> will be dynamic allocated
    int *a; // array -> will be dynamic allocated

    // print before allocate memory (1)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: %d\n", &a, a, *a);
    printf("\n");

    // allocate memory (2)
    p = (int *)malloc(sizeof(int));
    a = (int *)malloc(sizeof(int) * 10);

    // print after allocate, but before give a value to poinetrs (3)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: %d\n", &a, a, *a);
    printf("\n");

    // give a value to poinetrs (4)
    *p = 1;
    for (int i = 0; i < 10; i++) { a[i] = i; }

    // print after we gave a value to pointers (5)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: ", &a, a);
    // because a is an array we must use a loop for print 
    for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
    printf("\n");
    printf("\n");

    // free pointers (6)
    free(p);
    free(a);

    // print pointers after free (7)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: ", &a, a);
    // because a is an array we must use a loop for print 
    for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
    printf("\n");
    printf("\n");

    // try to change values after free (8)
    *p = 12;
    for (int i = 0; i < 10; i++) { a[i] = 3; }

    // print after (8)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: ", &a, a);
    // because a is an array we must use a loop for print 
    for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
    printf("\n");
    printf("\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

&p: 0xbfe5db64  p: 0xbfe5dc24   *p: -1075452506
&a: 0xbfe5db68  a: 0xbfe5dc2c   *a: -1075452502

&p: 0xbfe5db64  p: 0x8716008    *p: 0
&a: 0xbfe5db68  a: 0x8716018    *a: 0

&p: 0xbfe5db64  p: 0x8716008    *p: 1
&a: 0xbfe5db68  a: 0x8716018    *a: 0 1 2 3 4 5 6 7 8 9 

&p: 0xbfe5db64  p: 0x8716008    *p: 0
&a: 0xbfe5db68  a: 0x8716018    *a: 0 1 2 3 4 5 6 7 8 9 

&p: 0xbfe5db64  p: 0x8716008    *p: 12
&a: 0xbfe5db68  a: 0x8716018    *a: 3 3 3 3 3 3 3 3 3 3 
Run Code Online (Sandbox Code Playgroud)

现在,问题和观察:

  1. 当我为它提供内存之前打印指针时,为什么指针有一个随机值和一个随机地址指向它以及为什么它不是NULL?

  2. 在我们使用malloc之后,我们可以看到指针指向的地址已更改且其值为NULL,那么malloc真正做了什么?

  3. 在我们给它一个值并打印它之后,我们释放它并再次打印它,但是值和地址与数组的后面相同,但不是整数,为什么?那么免费真正做到了什么?

  4. 在我们释放空间之后,我们可以继续更改数组和整数的值,为什么在自由空间之后这可能?我们不需要重用malloc?

jua*_*nza 6

  1. 因为语言规范是这样说的.指针的值(即它指向的地址)是不确定的.它可以指向任何地方,就像一个int可以保持任何价值.读这些值,(如同你*p*a第一printfS)实际上是不确定的行为.

  2. 如果你指的是它所指的数据0,那就是偶然的.分配的内存不必归零.例如,它可能是先前分配的块的一部分,malloc然后是freed(free不会将内存清零,请参见下面的第3点.)

  3. 那也是偶然的.当你free记忆时,它不会被清零,也不必立即使用.它可以继续存储旧值,直到它被用于其他东西(例如,通过另一个分配)

  4. 这也是未定义的行为.你写的是你不再拥有的记忆.任何事情都可能发生.该计划可能已经崩溃.一个偶然的机会,似乎你可以成功地写入数组,很可能是因为内存仍未被其他任何会导致更明显的运行时错误的内容使用.