Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Zwolnienie pamięci, dowód.

Ostatnio zmodyfikowano 2014-09-20 16:33
Autor Wiadomość
kitsss
Temat założony przez niniejszego użytkownika
Zwolnienie pamięci, dowód.
» 2014-09-20 14:49:58
Jak wiadomo możemy dynamicznie zarezerwować pamięć za pomocą wskaźnika i operatora new. Potem możemy również tą pamięć zwolnić:
C/C++
long long * wsk = new long long;
* wsk = 666;
delete[] wsk;
I podręcznikowo zrozumiałem, że adres, czyli fragment pamięci, na który pokazywał wskaźnik o nazwie wsk, nie jest już użytkowany, został zwolniony i jest pamięcią wolną.

Tylko mam tak to pytanie, czemu ten wskaźnik pokazuje po zwolnieniu tej pamięci na ten sam adres:
C/C++
long long * wsk = new long long;
* wsk = 666;
cout << wsk << endl;
delete[] wsk;
cout << wsk << endl;
Czy to znaczy, że traktujemy od tej pory adres tego wskaźnika jako ,,śmiecie" które są na początku zdefiniowania jakiegokolwiek wskaźnika? Czyli po prostu ten wskaźnik na coś wciąż musi pokazywać, więc najprostszym sposobem jest, żeby pokazywał wciąż na adres, na który pokazywał ostatnio. Czy możliwe jest, że tworząc dużą ilość nowych zmiennych typu long long ten adres zostanie wykorzystany? wtedy byłoby to logiczne, bo podobno przestrzega się przed ponownym zwalnianiem pamięci ze wskaźnika, który już został raz zwolniony funkcją delete.

Próbowałem sam odpowiedzieć sobie na to pytanie, ale bez skutku:
C/C++
long long * wsk = new long long;
cout << sizeof( wsk ) << endl;
delete[] wsk;
cout << sizeof( wsk ) << endl;
Wyświetla mi się na ekranie dwa razy czwórka, czego też nie rozumiem. Skąd ta liczba? Nie powinno być 8, bo tyle zajmuje pamięć na obiekty typu long long?
P-117213
colorgreen19
» 2014-09-20 15:06:21
Skąd ta liczba? Nie powinno być 8, bo tyle zajmuje pamięć na obiekty typu long long?
wskaźniki są zawsze 4 bajtowe bo one tylko "mają" adres danej komórki. Sam obiekt danego typu, na który pokazuje wskaźnik jest większy. zobacz sobie
sizeof( * wsk )


przestrzega się przed ponownym zwalnianiem pamięci ze wskaźnika, który już został raz zwolniony funkcją delete.
Wysypie ci się program kiedy spróbujesz to zrobić
P-117215
Monika90
» 2014-09-20 15:21:35
delete[] nie jest poprawne, powinno być samo delete
P-117216
kitsss
Temat założony przez niniejszego użytkownika
» 2014-09-20 15:41:18
No dobrze, poprawiłem, ale nadal są dwie ósemki, nie powinno być początkowo osiem, a potem po zwolnieniu pamięci jakieś inne, mniejsze wartości?
C/C++
long long * wsk = new long long;
cout << sizeof( * wsk ) << endl;
delete wsk;
cout << sizeof( * wsk ) << endl;

Zaciekawiło mnie sprawdzenie jakimś sposobem, czy pamięć rzeczywiście się zwolni, bo ostatnio nie mając dostępu do pomocy naukowej pisałem program i zapomniałem, czy jeśli wskaźnik, dzięki któremu utworzyliśmy nowy obiekt operatorem new, zostanie usunięty, to czy ten obiekt do którego prowadził także zostanie usunięty, czy tylko stracimy z nim połączenie. Np:
C/C++
{
    char * wsk = new char;
    * wsk = 'c';
}
//Tutaj wskaznik wsk juz nie istnieje, ale co z obiektem, do ktorego prowadzil?

Teraz wiem, o ile się nie mylę, że obiekt będzie wciąż istniał, lecz nie możemy się nim posługiwać, ponieważ ten wskaźnik był do niego jedyną drogą. Straciliśmy go.

Ps. Dzięki Monika90, delete [] jest rzeczywiście do tablic tworzonych new :)
P-117219
colorgreen19
» 2014-09-20 15:57:26
obiekt będzie wciąż istniał, lecz nie możemy się nim posługiwać, ponieważ ten wskaźnik był do niego jedyną drogą. Straciliśmy go.
prawda

No dobrze, poprawiłem, ale nadal są dwie ósemki, nie powinno być początkowo osiem, a potem po zwolnieniu pamięci jakieś inne, mniejsze wartości?
niezbyt rozumiem cie.

C/C++
long long * wsk = new long long;
cout << sizeof( * wsk ) << endl;
delete wsk;
cout << sizeof( * wsk ) << endl;
sizeof( wsk )
 wypisze ci 4, ponieważ sprawdzasz rozmiar wskaźnika, a jak juz mówiłem wskaźniki sa 4 bajtowe bo one przechowują tylko adres komórki pamięci. Natomiast
sizeof( * wsk )
 wypisze ci 8, ponieważ sprawdzasz rozmiar obiektu, na który wskazuje wskaźnik, a typ tego obiektu to long long, który jest 8 bajtowy.

kasując
delete wsk;
 w ten sposób usuwasz obiekt, na który wskaźnik pokazuje, ale nie "usuwasz" adresu ze wskaźnika. czyli że
C/C++
long long * wsk = new long long;
cout << wsk << endl; //przykładowy adres wskaźnika 0xABCDEF
delete wsk;
cout << wsk << endl; //nadal ten sam adres 0xABCDEF

edit: co do
sizeof( * wsk )
 po wykonaniu
delete wsk;
 nie jestem pewien dlaczego nadal ci pokazuje 8 (jeśli dobrze cie zrozumiałem), ale zgaduje, skoro typ long long jest wielkości 8 bajtów, to wskaźnik pokazuje rozmiar tego typu, a nie już nie istniejącego obiektu (no to w tym wypadku program by się wysypał)
edit2: Monika90 odpowiedziała na to powyzej
P-117220
Monika90
» 2014-09-20 15:58:39
Wartość sizeof jest obliczana podczas kompilacji i jest to ilość bajtów zajmowana przez obiekt danego typu. Kompilator bierze pod uwagę tylko typ wyrażenia będącego argumentem sizeof, więc sizeof(*wsk), to to samo co sizeof(long long) - w używanym przez Ciebie kompialtorze jest to 8.
P-117221
kitsss
Temat założony przez niniejszego użytkownika
» 2014-09-20 16:33:50
Już wszystko rozumiem, dzięki wielkie colorgreen19 i Monika90 za pomoc!!! :) !!! Pozdrawiam ;]
P-117223
« 1 »
  Strona 1 z 1