доступ к массиву переменной длины после того, как его память должна была быть освобождена - PullRequest
0 голосов
/ 07 июня 2018

В настоящее время я изучаю массив переменной длины и автоматическое хранение.

У меня есть следующий код, который выделяет память для массива переменной длины myArray внутри функции vla и возвращает указатель на массив переменной длины из функции.

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

Я думал, что массив переменной длины принадлежит классу автоматического хранения (т. Е. Память для массива переменной длины будет выделена, когда мы войдем в функцию, содержащую массив переменной длины, и память будет автоматически освобожденапосле выхода из функции)

Таким образом, согласно этой логике, память, выделенная для массива myArray переменной длины, освобождается после того, как мы вернемся из метода vla, но почему я все еще могу правильно получить доступ к первому и второмуэлемент массива переменной длины?

Определено ли это поведение?или это просто неопределенное поведение, которое просто срабатывает?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Вы по-прежнему можете правильно обращаться к первому и второму элементу массива переменной длины, поскольку вы назначаете базовый адрес myArray для pointerToInt.Автоматические переменные имеют жизнь только внутри блока, но в этой программе мы используем указатель для доступа к данным в памяти, поскольку эта часть стека не выделена какой-либо другой программе, мы можем получить доступ к этой части стека.Если эта часть стека выделена какому-либо другому процессу, мы получим ошибку сегментации, когда мы пытаемся получить доступ к неавторизованной памяти

0 голосов
/ 07 июня 2018

myArray - это переменная стека / авто, созданная в памяти стека.Помните, что память всегда существует.Он просто принадлежит различным указателям, основанным на распределении и освобождении.Причина, по которой вы все еще можете получить доступ к одним и тем же значениям, заключается в том, что один и тот же фрагмент памяти не был назначен другому указателю и не был перезаписан.

Чтобы оценить это.Создайте другую функцию, которая выделяет ту же сумму из стека, но помещает другие значения.Или добавьте аргументы в одну и ту же функцию и вызовите ее дважды с разными значениями.Тогда вы увидите разницу.

#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.

...