简体   繁体   English

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

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

I saw the following code:我看到了以下代码:

#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;
}

This lines makes me very uncomfortable:这条线让我很不舒服:

free(vals);

vals is a pointer pointing to an array. vals是指向数组的指针。 This looks right, but I just have a difficult time internalizing it, I do not know why.这看起来不错,但我就是很难将其内化,我不知道为什么。

I am more used to the following style:我比较习惯下面的风格:

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

In this code, p is a pointer pointing to the start of a memory region for some integers, the malloc and free are symmetric in that they both work on a pointer type;在这段代码中, p是一个指针,指向一些整数的 memory 区域的开始,malloc 和 free 是对称的,因为它们都在指针类型上工作; yet the original code has malloc() working on a pointer to an array and free() a pointer.然而原始代码有malloc()处理指向数组的指针,而free()处理指针。

Out of curiosity, I modified the original code:出于好奇,我修改了原来的代码:

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

I was expecting this change will fail at compiler, the reason is *vals is an array now.我原以为这个更改会在编译器中失败,原因是*vals现在是一个数组。 But gcc is fine and valgrind does not complain memory leak.但是 gcc 很好,valgrind 不会抱怨 memory 泄漏。

I know C has a thing called array degenerates to pointer at function call.我知道 C 在 function 调用中有一个叫做数组退化为指针的东西。 But I just cannot internalize this stuff.但我就是无法将这些东西内化。 Sorry writing so long to describe a problem, wish you could see my struggle.抱歉写了这么长的时间来描述一个问题,希望你能看到我的挣扎。 Is there a definitive doc/stackoverflow/blog to clear this up - best C99 or later?是否有明确的文档/stackoverflow/blog 来解决这个问题——最好是 C99 或更高版本?

Thanks!谢谢!

writing free(*vals); free(*vals); is same as writing free(vals);与写free(vals);

edited your code to clear that a little bit编辑您的代码以清除一点

#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;
}

and this is the output:这是 output:

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

note that vals is Array pointer which means that its base type is an array of n integers where the pointer val is created in that stack and points to the whole array, not the first element only and that array is created in the heap , to illustrate, look at the following graph:请注意, vals是数组指针,这意味着它的基本类型是n 个整数的数组,其中指针val在该堆栈中创建并指向整个数组,而不仅仅是第一个元素,并且该数组是在heap创建的,以说明,请看下图:

在此处输入图像描述

so for example if you write:所以例如,如果你写:

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

the output will be: output 将是:

val is 00000207ef0c5d50
val+1 is 00000207ef0c5d78

note the difference between the 2 is about 40 bytes as val points to the whole array not only one element as in case of int *p = (int*)malloc(n * sizeof(int));请注意,两者之间的差异约为40个字节,因为val指向整个数组,而不仅仅是一个元素,如int *p = (int*)malloc(n * sizeof(int));

note that when I say it points to the whole array, I also mean it points to the base address of the array.请注意,当我说它指向整个数组时,我的意思也是它指向数组的基址。

in case of *Vals , look at the next graph:*Vals的情况下,请看下一张图:

在此处输入图像描述

*Vals is just an address of the first element of the array which is by the way is same as the base address of the array. *Vals只是数组第一个元素的地址,顺便说一下,它与数组的基地址相同。

refer to free() manual , they said:参考free() manual ,他们说:

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). free() function 释放 ptr 指向的 memory 空间,该空间必须由先前调用 malloc()、calloc() 或 realloc() 返回。 Otherwise, or if free(ptr) has already been called before, undefined behavior occurs.否则,或者如果之前已经调用过 free(ptr),则会发生未定义的行为。 If ptr is NULL, no operation is performed.如果 ptr 为 NULL,则不执行任何操作。

and what does malloc() function return? malloc() function 返回什么?

it returns the base address of your reserved space in heap, so writing free(vals);它返回堆中保留空间的基址,因此写成free(vals); is same as writing free(vals);与写free(vals);

This codes uses dynamic VLA .此代码使用动态 VLA I think that it may be easier to understand if the code is reformulated with a typedef .我认为如果代码用typedef重新表述可能更容易理解。

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

    ...
  
    free(vals);
}

Now it looks like a tivial use of a single dynamic object.现在它看起来像是对单个动态 object 的简单使用。

To access elements of an array first the pointer has to be dereferenced *vals forming an array, which decays to int* pointer suitable for [] operator.要首先访问数组的元素,必须取消引用指针*vals形成一个数组,该数组衰减为适合[]运算符的int*指针。

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

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