在应该释放其内存后访问可变长度数组

accessing variable length array after its memory should have been deallocated

目前正在研究变长数组和自动存储。

我有以下代码在函数 vla 内为可变长度数组 myArray 分配内存,并且 return 从函数指向可变长度数组的指针。

#include <stdio.h>

int * vla(int n){
    int myArray[n];

    myArray[0] = 10;
    myArray[1] = 11;

    int * pointerToInt = myArray;
    return pointerToInt;
}

int main(void){

    int * pointerToInt = vla(10);

    printf("%d, %d", pointerToInt[0], pointerToInt[1]); // prints 10, 11

    return 0;
}

我以为变长数组属于自动存储class(即当我们进入包含变长数组的函数时,会为变长数组分配内存,自动释放内存函数退出后)

所以按照这个逻辑,分配给myArray可变长度数组的内存在我们从vla方法return之后被释放了,但是为什么我仍然可以正确访问第一个和可变长度数组的第二个元素?

这个行为有定义吗?还是恰好起作用的未定义行为?

myArray 是在堆栈内存上创建的 stack/auto 变量。记住记忆永远存在。它只是由基于分配和释放的不同指针拥有。你仍然可以访问相同值的原因是同一块内存没有分配给另一个指针并且没有被覆盖。

评价一下。创建另一个函数,从堆栈分配相同数量但放置不同的值。或者在同一个函数中添加参数并用不同的值调用它两次。然后你就会看到不同。

#include <stdio.h>

int * vla(int n, int a, int b){
    int myArray[n];

    myArray[0] = a;
    myArray[1] = b;

    int * pointerToInt = myArray;
    return pointerToInt;
}

int main(void){

    int * pointerToInt = vla(10, 10, 11);
    vla(10, 20, 21); // over write stack

    printf("%d, %d", pointerToInt[0], pointerToInt[1]); // prints 20, 21

    return 0;
}

顺便说一下,从 vla 返回堆栈内存不是一个好主意。使用 malloc 系列函数从堆中分配动态内存。

您仍然可以正确访问可变长度数组的第一个和第二个元素,因为您正在将 myArray 的基地址分配给 pointerToInt。 auto变量只在块内有生命,但是在这个程序中我们使用指针访问内存中的数据,只要那部分堆栈没有分配给任何其他程序,我们就可以访问那部分堆栈。如果堆栈的那部分被分配给其他进程,我们将在尝试访问未经授权的内存时出现分段错误