Как free () влияет на адрес памяти в куче? - PullRequest
0 голосов
/ 23 октября 2018

Это назначение просит нас выделить две переменные типа int, используя malloc() (с именами var1 и var2), распечатать адреса каждой переменной (адрес указателя в стеке и адрес в куче).), затем используйте free(), чтобы освободить var1, снова напечатайте адреса, затем выделите еще один пробел в куче для var1 и напечатайте адреса в третий раз.Я считаю, что инструктор пытается показать нам, что адрес кучи для var1 должен измениться, но он всегда остается прежним ... если я не удаляю free(var1) из кода.Инструктор сделал аналогичную демонстрацию, но не использовал free() для освобождения каких-либо переменных, поэтому мы никогда не видели, как это должно работать.

Вот мой код:

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

void main()
{

int *var1 = (int*)malloc(sizeof(int)); 
*var1 = 1000;                   
int *var2 = (int*)malloc(sizeof(int)); 
*var2 = 2000;

printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1); 
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);

free(var1);

printf("AFTER DEALLOCATING var1 FROM THE HEAP\n");
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1); 
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);

var1 = (int*) malloc(sizeof(int));
*var1 = 1500;

printf("NEW MEMORY ADDRESS ALLOCATED FOR var1\n");
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1); 
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2); 

}

Этот код приводит к таким выводам:

Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

Как видите, адрес кучи не меняется для var1 когда я освобождаю его, и он не меняется, когда я снова выделяю пространство для var1.Однако, если я просто удаляю строку free(var1) из программы, она просто назначает вторую область памяти для var1 и указывает на нее в куче, которая имеет другой адрес памяти:

Addresses of var1 
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

(Просто для ясности, все, что я сделал, это удалил free(var1) из предыдущего кода, поэтому раздел «ПОСЛЕ ДЕАЛЛОКАЦИИ var1» теперь показывает тот же адрес кучи, что и предыдущий набор, но он изменяет адрес кучи в var1 втретий раздел.)

Кто-нибудь может мне сказать, что здесь происходит?Единственное логическое объяснение, которое я могу придумать, состоит в том, что когда я использую free() для освобождения var1 и затем печатаю адрес, это просто печатает последний адрес, на который он указал, и затем, когда я выделяю память дляvar1 во второй раз, просто "засыпать" предыдущий адрес новым значением var1.Имеет ли это смысл?У меня есть ошибки в моем коде, или это просто, как C ведет себя, когда освобождает память для переменной и затем перераспределяет ее?

Ответы [ 3 ]

0 голосов
/ 23 октября 2018

Совершенно нормально, что malloc может возвращать те же адреса, когда память освобождается и затем перераспределяется.Также было бы нормально, чтобы он возвращал разные адреса.

Если вы измените вызовы malloc для запроса других размеров, чем исходные распределения, вы можете получить другие адреса, так как старые блоки malloc подготовилиможет быть недостаточно для новых запросов.Но их может быть достаточно, поэтому адреса могут не измениться.

Кстати:

  • void main() неверно.Это должно быть int main(void).
  • Печать адреса после освобождения места, на которое он указывает, не поддерживается стандартом C.Это не редкость для «работы», но это не правильно.C 2018 6.2.4 2 говорит нам: «Значение указателя становится неопределенным, когда объект, на который он указывает (или только что прошел), достигает конца своего времени жизни». Когда объект, выделенный с помощью malloc, освобождается с помощью free,срок его службы заканчивается.
0 голосов
/ 23 октября 2018

В первом примере значение того, где указатель, используемый для указания на кучу, остается неизменным в стеке после free().Но вы больше не можете получить доступ к этому адресу.

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

0 голосов
/ 23 октября 2018

Единственное логическое объяснение, которое я могу придумать, заключается в том, что когда я использую free () для освобождения var1, а затем печатаю адрес, он просто печатает LAST-адрес, на который он указал

Вид верно.Освобождение указателя не влияет на содержимое указателя вообще.Или, если быть более точным, это значение неопределенно после освобождения.На самом деле, в соответствии со стандартом, вы даже не можете доверять указателю, содержащему адрес, который он делал до вызова free.Насколько я знаю, так будет в большинстве случаев, но вы не можете доверять этому.

Стандарт гласит:

C 2018 6.2.4 2: «Значение указателястановится неопределенным, когда объект, на который он указывает (или только что прошел), достигает конца своего жизненного цикла ».

Распространенной ошибкой является использование теста if(ptr == NULL) в качестве проверки правильности освобождения объекта.указатель.Это не будет работать.

...