繁体   English   中英

关于 malloc/free 中使用的数组指针的问题

[英]Question about pointer to array used in malloc/free

我看到了以下代码:

#include <stdlib.h>

void foo(char n)
{
    int (*vals)[n] = malloc(sizeof(int[n]));

    for (int i = 0; i < n; ++i)
        (*vals)[i] = i;

    free(vals);
}

int main(int argc, char **argv)
{
    foo(*(argv[1]));

    return 0;
}

这条线让我很不舒服:

free(vals);

vals是指向数组的指针。 这看起来不错,但我就是很难将其内化,我不知道为什么。

我比较习惯下面的风格:

int *p = (int*)malloc(n * sizeof(int));
......
free(p);

在这段代码中, p是一个指针,指向一些整数的 memory 区域的开始,malloc 和 free 是对称的,因为它们都在指针类型上工作; 然而原始代码有malloc()处理指向数组的指针,而free()处理指针。

出于好奇,我修改了原来的代码:

free(vals);  ==>  free(*vals);

我原以为这个更改会在编译器中失败,原因是*vals现在是一个数组。 但是 gcc 很好,valgrind 不会抱怨 memory 泄漏。

我知道 C 在 function 调用中有一个叫做数组退化为指针的东西。 但我就是无法将这些东西内化。 抱歉写了这么长的时间来描述一个问题,希望你能看到我的挣扎。 是否有明确的文档/stackoverflow/blog 来解决这个问题——最好是 C99 或更高版本?

谢谢!

free(*vals); 与写free(vals);

编辑您的代码以清除一点

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

void foo(char n)
{
    int (*vals)[n] = malloc(sizeof(int[n]));

    for (int i = 0; i < n; ++i)
        (*vals)[i] = i;

    printf("*val is %p\n", *vals);
    printf("val is %p\n", vals);
    printf("&val is %p\n", &vals);
    
    free(vals);
}

int main()
{
    foo(10);
    
    return 0;
}

这是 output:

*val is 0000018190365d50
val is 0000018190365d50
&val is 0000005d9dbff7b8

请注意, vals是数组指针,这意味着它的基本类型是n 个整数的数组,其中指针val在该堆栈中创建并指向整个数组,而不仅仅是第一个元素,并且该数组是在heap创建的,以说明,请看下图:

在此处输入图像描述

所以例如,如果你写:

printf("val is %p\n", vals);
printf("val+1 is %p\n", vals+1);

output 将是:

val is 00000207ef0c5d50
val+1 is 00000207ef0c5d78

请注意,两者之间的差异约为40个字节,因为val指向整个数组,而不仅仅是一个元素,如int *p = (int*)malloc(n * sizeof(int));

请注意,当我说它指向整个数组时,我的意思也是它指向数组的基址。

*Vals的情况下,请看下一张图:

在此处输入图像描述

*Vals只是数组第一个元素的地址,顺便说一下,它与数组的基地址相同。

参考free() manual ,他们说:

free() function 释放 ptr 指向的 memory 空间,该空间必须由先前调用 malloc()、calloc() 或 realloc() 返回。 否则,或者如果之前已经调用过 free(ptr),则会发生未定义的行为。 如果 ptr 为 NULL,则不执行任何操作。

malloc() function 返回什么?

它返回堆中保留空间的基址,因此写成free(vals); 与写free(vals);

此代码使用动态 VLA 我认为如果代码用typedef重新表述可能更容易理解。

void foo(char n)
{
    typedef int T[n];
    T *vals = malloc(sizeof(T));

    ...
  
    free(vals);
}

现在它看起来像是对单个动态 object 的简单使用。

要首先访问数组的元素,必须取消引用指针*vals形成一个数组,该数组衰减为适合[]运算符的int*指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM