| Bezpieczny malloc w ANSI C |
| 22.11.2007. | ||
|
Funkcja malloc jest przyczyną wielu ciężkich do wykrycia błędów. Wystarczy zapomnieć o pomnożeniu przez rozmiar elementu i bug gotowy. Dodatkowo w starszych kompilatorach wartość zwracaną przez malloc trzeba rzutować do określonego typu co na dłuższą metę jest bardzo pracochłonne i niewygodne.
Funkcja malloc jest przyczyną wielu ciężkich do wykrycia błędów. Wystarczy zapomnieć o pomnożeniu przez rozmiar elementu i bug gotowy. Dodatkowo w starszych kompilatorach wartość zwracaną przez malloc trzeba rzutować do określonego typu co na dłuższą metę jest bardzo pracochłonne i niewygodne. Tak mniej więcej wygląda standardowe wywołanie funkcji: Oczywiście zamiast sizeof(unsigned long int*) można wpisać 4 ale zmniejsza to przenośność kodu - w końcu niekoniecznie na wszystkich komputerach i nie na wszystkich systemach wskaźniki muszą mieć rozmiar 4 bajtów. W powyższym zapisie bardzo łatwo o pomyłkę a i czytelność jest znikoma. Jednak jest sposób aby unknąć wszystkich wyżej wymienionych problemów z malloc: z pomocą przychodzi nam preprocesor języka C. Bardzo prosto napisać makro, które wykona za nas rzutowanie oraz mnożenie przez rozmiar elementu. Poniższe makro jako argumenty przyjmuje typ elementów oraz ilość elementów do przydzielenia #define MALLOC(typ, ilosc) (typ*)malloc((ilosc)*sizeof(typ)) Makra uzywa się w ten sposób: Prawda, że czytelniejsze? ;> Kolejnym błędem podczas przydziału pamięci jest nie sprawdzanie czy pamięć została przydzielona (komu się chce za każdym razem pisać ). Na to również znajdzie się sposób: wystarczy zdefiniować funkcję, która będzie to sprawdzała: void* _new(size_t rozmiar) { void* p = malloc(rozmiar); if(p == NULL) { fprintf(stderr, "Out of memory!"); exit(EXIT_FAILURE); } return p; } oraz troche przerobić nasze makro: #define MALLOC(typ, ilosc) (typ*)_new((ilosc)*sizeof(typ)) Jeszcze jednym popełnianym błędem może być używanie malloc z argumentami naszego MALLOC (np. z przyzwyczajenia) można temu tak zaradzić: /*---plik my_alloc.h---*/ #define MALLOC(typ, ilosc) (typ*)_new((ilosc)*sizeof(typ)) #define malloc NIE_UŻYWAJ_BEZPOŚREDNIO_malloc! extern void* _new(size_t); /*---EOF---*/ /*---plik my_alloc.c---*/ #include <stdlib.h> #include <stdio.h> #include "my_alloc.h" #undef malloc void* _new(size_t rozmiar) { void* p = malloc(rozmiar); if(p == NULL) { fprintf(stderr, "Out of memory!"); exit(EXIT_FAILURE); } return p; } /*---EOF---*/ /*---plik main.c---*/ #include "my_alloc.h" int main(int argc, char *argv[]) { unsigned long int **p = MALLOC(unsigned long int*, 12); int *b = malloc(12); /*---Błąd!---*/ return 0; } /*---EOF---*/
Aby dodac komentarz zaloguj sie. Jesli nie masz konta, zalóz je sobie. Tylko zarejestrowani uzytkownicy moga pisac komentarze.
jpcomment 1.0 Beta |
||
| Zmieniony ( 28.11.2007. ) | ||