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ć: 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: 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: 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? |
|
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ć |
|
Monika90 |
» 2014-09-20 15:21:35 delete[] nie jest poprawne, powinno być samo delete |
|
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? 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: { char * wsk = new char; * wsk = 'c'; }
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 :) |
|
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. 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 long long * wsk = new long long; cout << wsk << endl; delete wsk; cout << wsk << endl;
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 |
|
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. |
|
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 ;] |
|
« 1 » |