Kurs programowania w C cz. 147

Nasza ocena:

5
Wyświetleń: 609
Komentarze: 0
Notatek.pl

Pobierz ten dokument za darmo

Podgląd dokumentu
Kurs programowania w C cz. 147 - strona 1

Fragment notatki:

166 ROZDZIAŁ 23. POWSZECHNE PRAKTYKI void free_string(struct string *s) { assert (s != NULL); free(s-data); /* zwalniamy pamięć zajmowaną przez strukturę */ free(s); /* usuwamy samą strukturę */ } Często łączy się destruktory z  zerowaniem zwolnionych wskaźników. Czasami dobrze jest ukryć definicję obiektu, Å¼eby mieć pewność, Å¼e użytkownicy nie utwo- rzą go ręcznie. Aby to zapewnić struktura jest definiowana w pliku Åºródłowym (lub prywat- nym nagłówku niedostępnym dla użytkowników) zamiast w pliku nagłówkowym, a deklaracja wyprzedzająca jest umieszczona w pliku nagłówkowym: struct string; struct string *create_string(const char *initial); void free_string(struct string *s); Zerowanie zwolnionych wskaźników Jak powiedziano już wcześniej, po wywołaniu free() dla wskaźnika, staje się on â€œwiszą- cym wskaźnikiem”. Co gorsze, większość nowoczesnych platform nie potrafi wykryć, kiedy taki wskaźnik jest używany zanim zostanie ponownie przypisany. Jednym z prostych rozwiązań tego problemu jest zapewnienie, Å¼e każdy wskaźnik jest zerowany natychmiast po zwolnieniu: free(p); p = NULL; Inaczej niż w przypadku â€œwiszących wskaźników”, na wielu nowoczesnych architektu- rach przy próbie użycia wyzerowanego wskaźnika pojawi się sprzętowy wyjątek. Dodatkowo, programy mogą zawierać sprawdzanie błędów dla zerowych wartości, ale nie dla â€œwiszących wskaźników”. Aby zapewnić, Å¼e jest to wykonywane dla każdego wskaźnika, możemy użyć makra: #define FREE(p) do { free(p); (p) = NULL; } while(0) (aby zobaczyć, dlaczego makro jest napisane w ten sposób, zobacz Konwencje pisania makr) Przy wykorzystaniu tej techniki destruktory powinny zerować wskaźnik, który przekazuje się do nich, więc argument musi być do nich przekazywany przez referencję. Na przykład, oto zaktualizowany destruktor z sekcji  Konstruktory i destruktory: void free_string(struct string **s) { assert(s != NULL && *s != NULL); FREE((*s)-data); /* zwalniamy pamięć zajmowaną przez strukturę */ FREE(*s); /* usuwamy strukturę */ } Niestety, ten idiom nie jest wstanie pomóc w wypadku wskazywania przez inne wskaźniki zwolnionej pamięci. Z tego powodu niektórzy eksperci C uważają go za niebezpieczny, jako kreujący fałszywe poczucie bezpieczeństwa.

(…)

… jest definiowana w pliku źródłowym (lub prywatnym nagłówku niedostępnym dla użytkowników) zamiast w pliku nagłówkowym, a deklaracja
wyprzedzająca jest umieszczona w pliku nagłówkowym:
struct string;
struct string *create_string(const char *initial);
void free_string(struct string *s);
Zerowanie zwolnionych wskaźników
Jak powiedziano już wcześniej, po wywołaniu free() dla wskaźnika, staje się on “wiszącym…
… powinny zerować wskaźnik, który przekazuje
się do nich, więc argument musi być do nich przekazywany przez referencję. Na przykład, oto
zaktualizowany destruktor z sekcji Konstruktory i destruktory:
void free_string(struct
{
assert(s != NULL &&
FREE((*s)->data); /*
FREE(*s);
/*
}
string **s)
*s != NULL);
zwalniamy pamięć zajmowaną przez strukturę */
usuwamy strukturę */
Niestety, ten idiom…
... zobacz całą notatkę



Komentarze użytkowników (0)

Zaloguj się, aby dodać komentarz