jektant kompilatora nie ponosi odpowiedzialności za śledzenie wykonania kodu i informo-wanie nas, że popełniliśmy błąd...

Linki


» Dzieci to nie książeczki do kolorowania. Nie da się wypełnić ich naszymi ulubionymi kolorami.
»
TPC /IC:\KATALOG PROGRAM /$A+/$B+i odpowiadaTPC -IC:\KATALOG PROGRAM -$A+ -$B+***; * Moemy take przy wypisywaniu opcji uy zapisu skrconego, kt* *t...
»
"PPP (point-to-point) support"Tutaj odpowiedz yes, bedziesz mol laczyc sie za pomoca PPP z providerem...
»
– Tak jest, kapitanie – odpowiedział k’vaernijski dowódca...
»
Kiedy korzystasz z biblioteki open-uri, wystarczy, że wpiszesz instrukcję open() z adresem URL, a skrypt zwróci odpowiednią stronę WWW...
»
dawa mi rne pytania,na ktre mu do rzeczy odpowiadaem,wyj wszy cudzoziemsk wy-mow,niektre bdy i wyraenia chopskie,ktrych si w domu gospodarza mego...
»
Psychologia społeczna jest nauką empiryczną i dysponuje rozwiniętą grupą metod, które pomagają odpowiedzieć na pytania dotyczące zachowań społecznych,...
»
kiej trawy, farba, jeden lub wiê- cej kaczanów kukurydzy (odpowiadaj¹ce Matce Kukurydzy); skór-ki ró¿nych ptaków i czasami skalp...
»
passwd chatTa opcja okrela seri acuchw: wysyane dane-odpowied, przypominajc uniksowy skrypt chat i uywan do wsppracy z programem zmieniajcym hasa w...
»
Rozmowa miała zosta nagrana w korytarzu, eby poziom hałasu i odgłosy z zewn trz odpowiadały miejscu, w którym 2J miał ich rzekomo podsłuchiwa...
»
— Byłem — odpowiedziałem z wolna, bo naraz jak gdyby podłoga jęła odpływać mi spod stóp...

Dzieci to nie książeczki do kolorowania. Nie da się wypełnić ich naszymi ulubionymi kolorami.

Taki kod jest składniowo poprawny. Nie oznacza to także,
że taki program skompiluje się, uruchomi, wykona i będzie wykazywać w sposób powtarzal-
ny nieprawidłowe rezultaty. To znaczy tylko tyle, że rezultaty działania takiego kodu okażą
się nieokreślone. W istocie rezultaty te są zależne od platformy uruchomieniowej, od tego,
w jaki sposób aplikacja okaże się zależna od środowiska operacyjnego. System może się
zawiesić, program może zadziałać w sposób nieprawidłowy (znienacka), może też przez pe-
wien czas działać całkowicie poprawnie (do czasu).
Na listingu 11.3 pokazano kompletny program zawierający implementację tej wadliwej
konstrukcji. Wyjściowy wydruk tego programu na monitorze autora przedstawiono na ry-
sunku 11.10.
Listing 11.3. Przeciążenie operatora konkatenacji z obiektem — parametrem przekazywanym
poprzez wartość
;
7 0 !
!"
; #$ & & &( )
; 7 & & &(
/; 5 ( 0
2# ; && ( !& ;
582
Część II n Programowanie obiektowe w C++
Rysunek 11.10.
Wydruk wyjściowy
programu
z listingu 11.3
1 7 ) ! &(
7 &<& !
,
; "";
#
# =2%>
1 ##?@AA 3 %
=$> # $ , 54 5) ( B ( CD
; ""; 7
# 5) & ()
# =2%> 5 (.( ) (
1 ##?@AA 3 % < 0 5
, &( () & 0
; ""/;
, 0 &<&6
; "" 2# ; )E
# 2 5& 5)E
7 # = 2 %> (.. )E (
1 ##?@AA 3 % < 0 5
&( . 0)E & &
( . 0)E &
F )E
# , F &.E
7 ; "" 4 .
,
; ""1 => ! . 0.
*% 5
=*%> # $ , &4 54 &'
; G
" ; G (
; ?
" ; ? F '()E <+
# & ( CD
Rozdział 11. n Konstruktory i destruktory — potencjalne problemy583
# & ( CD
2# 2#
# & ( CD
# & !0 CD
1+A 1 ! + & 0
" ; ? ( H!H+ * &
# OOOO
$
,
Zauważ, że te wszystkie okropne rzeczy dzieją się w chwili zakończenia działania funkcji.
Pierwsze nieprzyjemne zdarzenie miało miejsce wtedy, gdy przeciążająca funkcja operatorowa
zbliżała się ku końcowi i musiało (zgodnie z zasadami) nastąpić wywołanie de-
struktora wobec formalnego parametru tej funkcji. Wtedy to bieżący argument tej funkcji,
obiekt , został pozbawiony przydzielonej mu na stercie dynamicznej pamięci. Drugie nie-
miłe zdarzenie miało miejsce, gdy funkcja-klient, zbliżała się ku końcowi i obiekt
musiał zostać usunięty, ponieważ kończył się zakres przestrzeni widoczności jego nazwy
(obiekt wychodził poza zakres — ang. out of scope). Jego pamięć na stercie została wtedy
zwolniona i zwrócona po raz wtóry.
W istocie, w C++ błędem jest powtórne zwracanie dynamicznej pamięci poprzez ponowne
użycie operatora wobec tego samego niezerowego wskaźnika. Jeśli wskaźnik za-
wiera ,-.., to nie jest błąd, lecz operacja pusta (ang. no operation). Niektórzy programiści próbują rozwiązać ten problem poprzez przypisanie wskaźnikowi do pamięci na stercie wartości ,-.. w obrębie destruktora4.
; ""/;
# $ ! &.E '
,
To sympatycznie wyglądający pomysł, ale nie działa zgodnie z ich intencjami. Taki wskaź-
nik, który został ustawiony na zero, należy do obiektu, który to obiekt będzie usuwany w ciągu
najbliższych mikrosekund. Nadal istnieje drugi wskaźnik, który wskazuje ten sam adres pamięci
i mógłby zostać wyzerowany, ale nie jest dostępny dla takiego destruktora, wykonującego
się przecież w odniesieniu do innego obiektu. Poza tym, nawet gdyby to zadziałało, stanowi-
łoby to tylko środek zapobiegający wykonaniu błędnej instrukcji, nie powodując przecież
przywrócenia pamięci, która została omyłkowo skasowana.
Jak „stąd” przejść „tam”?
Czy autor przestraszył czytelnika? Jeśli tak, to taka właśnie była intencja. Jeśli nie, nie szkodzi,
pamiętaj jednak zawsze, by zatroszczyć się o dynamiczne zarządzanie pamięcią w swoich
programach. Nawet jeśli na twoim komputerze programy działają prawidłowo, to jeszcze nie
jest oczywisty dowód, że dany program jest poprawny (dodajmy to do listy naszych zasad
testowania programów).
4 Taki wskaźnik przestaje wskazywać cokolwiek — przyp. tłum.
584
Część II n Programowanie obiektowe w C++
Program może działać bez żadnych zgrzytów miesiącami i latami, a następnie, np. po zain-
stalowaniu w systemie jakiejś innej, zupełnie z nim nie związanej aplikacji bądź po aktualizacji
systemu operacyjnego do nowszej wersji Windows™ zmieni się sposób wykorzystywania
pamięci i nasz program doprowadzi do katastrofy. Taki program może także dawać nieprawi-
dłowe rezultaty, które nie zostaną dostrzeżone, ponieważ działał przecież poprawnie przez
wiele miesięcy, a nawet przez wiele lat. Co się wtedy dzieje? Czy przeklinać Microsoft, bo

Powered by MyScript