| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
Muistidebuggeriweicco 11.10.03 13:41 Luokka, jonka avulla voi kätevästi debugata muistivuotoja.
/* * Headeri. * Muista laittaa jotain #ifndef _BLAA_ #define _BLAA_ #endif * härpäkkeitä headerin ympärille */ #include <stdlib.h> #include <string.h> #include <stdio.h> // Use these macros to allocate and free memory // Unless you want to write file names and line index yourself #ifdef _DEBUG #define MALLOC(CWMemoryObject, BlockLength) CWMemoryObject->Allocate(BlockLength, __FILE__, __LINE__) #define FREE(CWMemoryObject, MemoryBlock) CWMemoryObject->Free(MemoryBlock, __FILE__, __LINE__) #else #define MALLOC(CWMemoryObject, BlockLength) CWMemoryObject->Allocate(BlockLength, "na", -1) #define FREE(CWMemoryObject, MemoryBlock) CWMemoryObject->Free(MemoryBlock, "na", -1) #endif /** * @class CWMemory * @brief Memory handling class. Helps tracking down memory leaks. */ class CWMemory { private: /** Private constructor */ CWMemory(unsigned int blocks); /** Private destructor */ virtual ~CWMemory(); public: /** Create new CWMemory object. Only one instance per process is allowed. */ static CWMemory *Create(unsigned int blocks = 10); /** Destroys instance */ void Destroy() { delete this; } /** Allocates block of memory */ void *Allocate(const unsigned long length, char *file, int line); /** Frees previously allocated memory block */ void Free(void *memblck, const char *file, int line); /** Cleans up internal database */ void Flush(); /** Saves memory allocation info to file */ void ToFile(FILE *fOut) const; private: struct _mem_object_t { _mem_object_t(void *d, char *f, int r, int l) { data = d; data_length = l; alloc_file = strdup(f); alloc_row = r; next = NULL; freed_file = NULL; freed_row = -1; } struct _mem_object_t *next; void *data; int data_length; char *alloc_file, *freed_file; int alloc_row, freed_row; }; static bool m_IsInstance; struct _mem_object_t *m_List; // List handling stuff void Push(struct _mem_object_t *p); struct _mem_object_t *Find(void *mem) const; void Remove(struct _mem_object_t *p); }; /* * CPP tiedosto. * Mmuista includata ylempi headeri mukaan. */ bool CWMemory::m_IsInstance = false; CWMemory::CWMemory(unsigned int blocks) { m_List = NULL; } CWMemory::~CWMemory() { m_IsInstance = false; while (m_List) { struct _mem_object_t *tmp = m_List; m_List = m_List->next; free(tmp->alloc_file); free(tmp->freed_file); free(tmp); } } CWMemory *CWMemory::Create(unsigned int blocks/* = 10*/) { if (m_IsInstance) return NULL; m_IsInstance = true; CWMemory *This = new CWMemory(blocks); return This; } void *CWMemory::Allocate(const unsigned long length, char *file, int line) { struct _mem_object_t *mem = Find(NULL); if (mem == NULL) { mem = new struct _mem_object_t(malloc(length), file, line, length); Push(mem); } else { mem->data = malloc(length); free(mem->alloc_file); mem->alloc_file = strdup(file); mem->alloc_row = line; } return mem->data; } void CWMemory::Free(void *memblck, const char *file, int line) { struct _mem_object_t *tmp = Find(memblck); if (tmp == NULL) return; free(tmp->data); tmp->data = NULL; if (tmp->freed_file) free(tmp->freed_file); tmp->freed_file = strdup(file); tmp->freed_row = line; } void CWMemory::Flush() { struct _mem_object_t *tmp = NULL; while ((tmp = Find(NULL))) { Remove(tmp); if (tmp->alloc_file) free(tmp->alloc_file); if (tmp->freed_file) free(tmp->freed_file); delete tmp; } } void CWMemory::ToFile(FILE *fOut) const { fprintf(fOut, "Syntax:\n"); fprintf(fOut, "File where allocated | Line where allocated | Amount | File where freed | Line where freed\n"); struct _mem_object_t *tmp = m_List; while (tmp) { fprintf(fOut, "%s | %i | %i | %s | %i\n", tmp->alloc_file, tmp->alloc_row, tmp->data_length, tmp->freed_file, tmp->freed_row); tmp = tmp->next; } } void CWMemory::Push(struct _mem_object_t *p) { struct _mem_object_t *tmp = m_List; if (tmp == NULL) { m_List = p; return; } while (tmp->next) tmp = tmp->next; tmp->next = p; } struct CWMemory::_mem_object_t *CWMemory::Find(void *mem) const { struct _mem_object_t *tmp = m_List; if (tmp) { do { if (tmp->data == mem) return tmp; tmp = tmp->next; } while (tmp); } return NULL; } void CWMemory::Remove(struct _mem_object_t *p) { struct _mem_object_t *tmp = m_List; struct _mem_object_t *prv = NULL; while (tmp) { if (tmp == p) { if (prv) prv->next = tmp->next; else m_List = tmp->next; break; } tmp = tmp->next; } } /* * Esimerkkikoodipätkä. * Muista includata headeri, jos laitat koodit eri tiedostoihin. */ int main(void) { CWMemory *pMemory = CWMemory::Create(20); void *p1 = MALLOC(pMemory, 100); void *p2 = MALLOC(pMemory, 100); FREE(pMemory, p1); FREE(pMemory, p2); FILE *p = fopen("out.log", "w"); pMemory->ToFile(p); fclose(p); pMemory->Flush(); pMemory->Destroy(); return 0; } weicco 13:43 11.10.03 Karvalakkiversio. Puuttuu varmaan n+1 toimintoa, mutta tämän tarkoitus onkin havainnollistaa, kuinka metsästää tiukassa olevia muistivuotoja. Tämän koodin edeltäjä pelasti minut ainakin parista tiukasta paikasta. psd 02:12 16.10.03 Eipä tuota voi käyttää kuin perustyypeille. Luokille vaatisi placement new:n käyttöä ja destructoreiden manuaalista kutsumista. C++:lla muistimanagerin toteuttaminen käytännössä vaatii operator new/deleten korvaamista. Tämän saa tehtyä käyttäjälle näkymättömästi. Oma säätöni löytyy osoitteesta http://www.cs.helsinki.fi/u/hiekkama/memory_manager.zip |
![]() Haku
|