W jaki sposób w pamięci zaimplementowany jest wskaźnik i co faktycznie robi metoda delete?

0

Dzień dobry wszystkim!

Niedawno w pewnej dyskusji wyniknął temat "usuwania usuniętych wskaźników." Chodzi o to, że następujący kod nie powoduje protestów ze strony kompilatora:

int* a = new int();
delete a;
delete a;

Zastanawiamy się w jaki sposób w pamięci zaimplementowany jest wskaźnik i co faktycznie robi metoda delete. Mam swoją teorię - że jest to po prostu fragment pamięci (odpowiednia liczba bajtów) w którym zapisujemy adres na który wskaźnik ma wskazywać a delete ten obszar zwalnia i pozwala go nadpisać inną zmienną. Jeśli jednak mam rację, to taki kod jest bardzo niebezpieczny - może spowodować usunięcie zmiennej, której wcale usuwać nie zamierzamy (jeśli pomiędzy jednym delete a drugim coś tam zostało zapisane). Obstawiałabym zatem, że niezgłoszenie przez kompilator choćby ostrzeżenia jest błędem. Czy ktoś mi może opowiedzieć mniej więcej jak to rzeczywiście działa, na ile mam rację i dlaczego jest jak jest? Będę wdzięczna :)

2

tak, masz rację - zachowanie podwójnego delete nie jest ustandaryzowane i w zależności od kompilatora mogą stać się różne rzeczy, w tym uszkodzenie danych w pamięci i wysypanie się programu
aby tego uniknąć najlepiej zaraz po delete ustawić wskaźnik na NULL - w ten sposób masz pewność że drugie delete nie zaszkodzi bo delete na wyzerowanym wskaźniku nie robi niczego

Malvinka87 napisał(a):

Jeśli jednak mam rację, to taki kod jest bardzo niebezpieczny - może spowodować usunięcie zmiennej, której wcale usuwać nie zamierzamy (jeśli pomiędzy jednym delete a drugim coś tam zostało zapisane). Obstawiałabym zatem, że niezgłoszenie przez kompilator choćby ostrzeżenia jest błędem

i rzeczywiście tak się dzieje:

http://ideone.com/97QbBG

w tym przykładzie drugie delete usuwa inną zmienną

ogólnie operacje na wskaźnikach są niebezpieczne - jest tyle możliwych kombinacji że kompilator i tak nie przewidzi wszystkiego; w takim C# fragment kodu ze wskaźnikami musi być oznaczony jako unsafe ;)
jest dużo mechanizmów temu przeciwdziałających, m.in. smart pointery
zapewne niektóre IDE wygenerują ostrzeżenie ale moim zdaniem nie ma sensu - C++ to taki język gdzie błąd w jednym miejscu może doprowadzić do zmiany zachowania całkiem innego fragmentu kodu - taki to już język, trzeba się pilnować

1

@Malvinka87 nie do końca masz rację. delete niczego nie usuwa. Tylko oznacza pewien blok pamięci operacyjnej jako wolny i program może go znów przydzielić kiedy zajdzie taka potrzeba. Ale żadne usuwanie nie ma miejsca. Mozesz spróbować zaalokować pamięć, wpisać do niej jakąś wartość. Zrobić delete a potem wypisać wartość z tego zwolnionego wskaźnika. Przy odrobinie szczęścia odczytasz spodziewaną wartość.
Ale faktycznie wywołnie delete wielokrotnie to zwykle źródło problemów i najczęściej wysypanie się programu.

0

Dziękuję Wam wszystkim za odpowiedzi.
A możecie jeszcze opisać jak to jest z implementacją wskaźników w pamięci?

4

Wskaźnik to liczba, która jest adresem zmiennej/funkcji w pamięci.

1 użytkowników online, w tym zalogowanych: 0, gości: 1