Faces Of Nature - Informatyka - C++ Memory Leak
Faces of nature   »  

Informatyka  »   C++ Memory Leak

(1) Memory Leak (Wyciek pamięci)

Prosta metoda na wykrycie wycieków pamięci w C++ (memory leak) wykorzystującej przeładowanie operatorów new, new[] i delete, delete[].


(a) Metoda

  1. Podczas tworzenia obiektu za pomocą operatorów new, new[] będziemy tworzyli także blok struct SMemList z informacją na temat wielkości rezerwowanego obszaru, flagi tablica czy nie, ew. pliku i linii w którym został operator użyty.
    struct SMemList
    {
    	struct	SMemList *next, *prev;
    	size_t 	size;
    	bool	array;
    	char 	*file;
    	unsigned int line;
    	int	tag;
    };
    		
    Poszczególne bloki będą ze sobą połączone wskaźnikami next, prev w postaci listy z jednym elementem korzeniem, do którego będziemy dodawać nowe elementy listy. Umożliwi nam to późniejsze sprawdzenie, czy wszystkie obszary pamięci zostały zwolnione.
  2. Usuwanie obszaru pamięci operatorem delete,delete[] będzie wiązało się z usunięciem danego bloku powyższej listy. Na koniec wykonywania programu, lista bloków powinna składać się tylko z korzenia. Jeśli będą na niej elementy inne - będą one właśnie takimi wyciekami.

(b) Organizacja bloków


Podczas rezerwowania pamięci dla obiektu OBJ np. tak:

	OBJ *ptr = new OBJ();

nasz przeładowany operator new zarezerwuje pamięć rozmiaru

	sizeof(SMemList) + sizeof(OBJ);

Na początku zarezerwowanego obszaru znajdzie się blok SMemList, następnie obiekt OBJ. Operator new, new[] zwraca wskaźnik void*, zatem zwrócimy adres nie początku zarezerwowanego wyżej bloku pamięci a początek obszaru dla OBJ:

	void * operator new(size_t _size)
	{
		...
		void *ptr = malloc(sizeof(SMemList) + _size);
		return ptr + sizeof(SMemList);
	}

(c) Usuwanie pamięci


Podczas zwalniania pamięci operatorami delete, delete[] będziemy wejściowy wskaźnik przesuwać o rozmiar SMemList i sprawdzać, czy faktycznie użyliśmy dobrego operatora (delete, delete[]) czy np. pole tag jest poprawne (ustawiamy je wcześniej dla sprawdzenia poprawności tego kroku), moglibysmy bowiem zwalniać 'nieswoją' pamięć.

Ostatecznie zwalniamy pamięć całego bloku SMemList i OBJ oraz aktualizujemy listę bloków pamięci usuwając z niej aktualny element.


(d) Informacje dodatkowe

W bloku SMemList możemy zapisać informacje na temat pliku oraz linii, w której został użyty operator new, new[] np. za pomocą makro

	#define new new(__FILE__, __LINE__)
	

które automatycznie wstawi nam nazwe pliku, linię wystąpienia instrukcji. I w ten sposób wykorzystamy przeładowane operatory

	void* operator new(size_t _size, 
		char *_file, unsigned int _line);
		
	void* operator new[](size_t _size, 
		char *_file, unsigned int _line);
	

(e) Przykład użycia

1. Do projektu dołączamy plik Debug.cpp, który przeładuje nam operatory, stworzy listę oraz obsługę. Sprawdzanie listy następuje podczas usunięcia ostatniego statycznego elementu static _exit_detect _exit_counter;

Jeśli natomiast chcemy również zachować informację o nazwie pliku i linii wystąpienia operatorów, 2. includujemy plik Debug.h


Download:

Faces of nature   »  

Informatyka  »   C++ Memory Leak