/* Released all unfree'd memory from all pools */ void mem_release_all() { #if defined(MEM_RECLAIM) OStream *f = NULL; MEMNODE *p, *tmp; size_t totsize; Send_Progress("Reclaiming memory", PROGRESS_RECLAIMING_MEMORY); p = memlist; totsize = 0; #if defined(MEM_TRACE) if (p != NULL) f = New_OStream(MEM_LOG_FNAME, POV_File_Data_LOG, true); #endif while (p != NULL) { #if defined(MEM_TRACE) #if defined(MEM_TAG) if (!mem_check_tag(p)) Debug_Info("mem_release_all(): Memory pointer corrupt!\n"); #endif /* MEM_TAG */ totsize += (p->size - NODESIZE - (MEM_GUARD_SIZE * 2)); if (!leak_msg) { Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME); leak_msg = true; } if (f != NULL) f->printf("File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size - NODESIZE - (MEM_GUARD_SIZE * 2))); #endif #if defined(MEM_STATS) /* This is after we have printed stats, and this may slow us down a little, */ /* so we may want to simply re-initialize the mem-stats at the end of this loop. */ mem_stats_free(p->size); #endif tmp = p; p = p->next; remove_node(tmp); FREE(tmp); } if (f != NULL) delete f; if (totsize > 0) Debug_Info("\n%lu bytes reclaimed\n", totsize); poolno = 0; memlist = NULL; #endif #if defined(MEM_STATS) /* reinitialize the stats structure for next time through */ mem_stats_init(); #endif }
/* Releases all unfree'd memory from current memory pool */ void mem_release() { #if defined(MEM_RECLAIM) OStream *f = NULL; MEMNODE *p, *tmp; size_t totsize; p = memlist; totsize = 0; #if defined(MEM_TRACE) if (p != NULL && (p->poolno == poolno)) f = New_OStream(MEM_LOG_FNAME, POV_File_Data_LOG, true); #endif /* MEM_TRACE */ while (p != NULL && (p->poolno == poolno)) { #if defined(MEM_TRACE) #if defined(MEM_TAG) if (!mem_check_tag(p)) Debug_Info("mem_release(): Memory pointer corrupt!\n"); #endif /* MEM_TAG */ totsize += (p->size - NODESIZE - (MEM_GUARD_SIZE * 2)); if (!leak_msg) { Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME); leak_msg = true; } if (f != NULL) f->printf("File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size - NODESIZE - (MEM_GUARD_SIZE * 2))); #endif /* MEM_TRACE */ #if defined(MEM_STATS) mem_stats_free(p->size); #endif tmp = p; p = p->next; remove_node(tmp); FREE(tmp); } if (f != NULL) delete f; if (totsize > 0) Debug_Info("%lu bytes reclaimed (pool #%d)\n", totsize, poolno); if (poolno > 0) poolno--; #if defined(MEM_STATS) /* reinitialize the stats structure for next time through */ mem_stats_init(); #endif #endif /* MEM_RECLAIM */ }
void *pov_realloc(void *ptr, size_t size, const char *file, int line, const char *msg) { void *block; #if defined(MEM_STATS) size_t oldsize; #endif #if defined(MEM_HEADER) MEMNODE *node; #endif #if defined(MEM_RECLAIM) MEMNODE *prev; MEMNODE *next; #endif #if defined(MEM_PREFILL) || defined(MEM_GUARD) char *memptr; size_t i; #endif if (size == 0) { if (ptr) pov_free(ptr, file, line); return NULL; } else if (ptr == NULL) return pov_malloc(size, file, line, msg); block = (void *)((char *)ptr - NODESIZE - MEM_GUARD_SIZE); #if defined(MEM_GUARD) memptr = (char *)block + NODESIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) { if(memptr[i] != mem_guard_string[i % mem_guard_string_len]) { Warning(0, "Damaged start guard detected in resized block (File: %s Line: %d).", file, line); break; } } memptr = (char *)block + ((MEMNODE *)block)->size - MEM_GUARD_SIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) { if(memptr[i] != mem_guard_string[i % mem_guard_string_len]) { Warning(0, "Damaged end guard detected in resized block (File: %s Line: %d).", file, line); break; } } #endif #if defined(MEM_HEADER) node = (MEMNODE *) block; #endif #if defined(MEM_TAG) if (node->tag != MEMTAG_VALUE) Error("Attempt to realloc invalid block (File: %s Line: %d).", file, line); node->tag = ~node->tag; #endif #if defined(MEM_RECLAIM) prev = node->prev; next = node->next; #endif #if defined(MEM_STATS) oldsize = ((MEMNODE *)block)->size; #if defined(MEM_PREFILL) memptr = (char *)block + NODESIZE + MEM_GUARD_SIZE; for(i = size; i < oldsize - NODESIZE - (MEM_GUARD_SIZE * 2); i++) memptr[i] = mem_clear_string[i % mem_clear_string_len]; #endif #endif block = (void *)REALLOC(block, NODESIZE + (MEM_GUARD_SIZE * 2) + size); if (block == NULL) MAError(msg, size); #if defined(MEM_STATS) /* REALLOC does an implied FREE... */ mem_stats_free(oldsize); /* ...and an implied MALLOC... */ mem_stats_alloc(NODESIZE + (MEM_GUARD_SIZE * 2) + size, file, line); #if defined(MEM_PREFILL) memptr = (char *)block + NODESIZE + MEM_GUARD_SIZE; for(i = oldsize - NODESIZE - (MEM_GUARD_SIZE * 2); i < size; i++) memptr[i] = mem_prefill_string[i % mem_prefill_string_len]; #endif #endif #if defined(MEM_HEADER) node = (MEMNODE *) block; #endif #if defined(MEM_TAG) node->tag = MEMTAG_VALUE; #endif #if defined(MEM_TRACE) || defined(MEM_STATS) node->size = size + NODESIZE + (MEM_GUARD_SIZE * 2); #endif #if defined(MEM_TRACE) node->file = file; node->line = line; #endif #if defined(MEM_GUARD) memptr = (char *)block + NODESIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) memptr[i] = mem_guard_string[i % mem_guard_string_len]; memptr = (char *)block + ((MEMNODE *)block)->size - MEM_GUARD_SIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) memptr[i] = mem_guard_string[i % mem_guard_string_len]; #endif #if defined(MEM_RECLAIM) if (prev == NULL) memlist = node; else prev->next = node; if (node->next != NULL) node->next->prev = node; if (next != NULL) next->prev = node; #endif return (void *)((char *)block + NODESIZE + MEM_GUARD_SIZE); }
void pov_free(void *ptr, const char *file, int line) { void *block; #if defined(MEM_HEADER) MEMNODE *node; #endif #if defined(MEM_PREFILL) || defined(MEM_GUARD) char *memptr; size_t size; size_t i; #endif if (ptr == NULL) Error("Attempt to free NULL pointer (File: %s Line: %d).", file, line); block = (void *)((char *)ptr - NODESIZE - MEM_GUARD_SIZE); #if defined(MEM_HEADER) node = (MEMNODE *) block; #endif #if defined(MEM_TAG) #if defined(MEM_PREFILL) size = ((MEMNODE *)block)->size; memptr = (char *)block + NODESIZE + MEM_GUARD_SIZE; for(i = 0; i < size - NODESIZE - (MEM_GUARD_SIZE * 2); i++) memptr[i] = mem_clear_string[i % mem_clear_string_len]; #endif if (node->tag == ~MEMTAG_VALUE) { Warning(0, "Attempt to free already free'd block (File: %s Line: %d).", file, line); return; } else if (node->tag != MEMTAG_VALUE) { Warning(0, "Attempt to free invalid block (File: %s Line: %d).", file, line); return; } #endif #if defined(MEM_GUARD) memptr = (char *)block + NODESIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) { if(memptr[i] != mem_guard_string[i % mem_guard_string_len]) { Warning(0, "Damaged start guard detected in free'd block (File: %s Line: %d).", file, line); break; } } memptr = (char *)block + ((MEMNODE *)block)->size - MEM_GUARD_SIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) { if(memptr[i] != mem_guard_string[i % mem_guard_string_len]) { Warning(0, "Damaged end guard detected in free'd block (File: %s Line: %d).", file, line); break; } } #endif #if defined(MEM_RECLAIM) remove_node(node); #endif #if defined(MEM_TAG) /* do this After remove_node, so remove_node can check validity of nodes */ node->tag = ~node->tag; #endif #if defined(MEM_STATS) mem_stats_free(((MEMNODE*)block)->size); #endif FREE(block); }
void pov_free(void *ptr, const char *file, int line) { void *block; #if defined(MEM_HEADER) MEMNODE *node; #endif #if defined(MEM_PREFILL) || defined(MEM_GUARD) char *memptr; size_t size; size_t i; #endif if (ptr == NULL) throw pov_base::Exception(NULL, file, (unsigned int)line, "Attempt to free NULL pointer."); block = reinterpret_cast<void *>(reinterpret_cast<char *>(ptr) - NODESIZE - MEM_GUARD_SIZE); #if defined(MEM_HEADER) node = reinterpret_cast<MEMNODE *>(block); #endif #if defined(MEM_TAG) if (node->tag == ~MEMTAG_VALUE) { Warning(kWarningGeneral, "Attempt to free already free'd block (File: %s Line: %d).", file, line); return; } else if (node->tag != MEMTAG_VALUE) { Warning(kWarningGeneral, "Attempt to free invalid block (File: %s Line: %d).", file, line); return; } #endif #if defined(MEM_GUARD) memptr = reinterpret_cast<char *>(block) + NODESIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) { if(memptr[i] != mem_guard_string[i % mem_guard_string_len]) { Warning(kWarningGeneral, "Damaged start guard detected in free'd block (File: %s Line: %d).", file, line); break; } } memptr = reinterpret_cast<char *>(block) + (reinterpret_cast<MEMNODE *>(block))->size - MEM_GUARD_SIZE; for(i = 0; i < MEM_GUARD_SIZE; i++) { if(memptr[i] != mem_guard_string[i % mem_guard_string_len]) { Warning(kWarningGeneral, "Damaged end guard detected in free'd block (File: %s Line: %d).", file, line); break; } } #endif #if defined(MEM_RECLAIM) remove_node(node); #endif #if defined(MEM_TAG) /* do this After remove_node, so remove_node can check validity of nodes */ node->tag = ~node->tag; #endif #if defined(MEM_STATS) mem_stats_free((reinterpret_cast<MEMNODE*>(block))->size); #endif #if defined(MEM_PREFILL) size = (reinterpret_cast<MEMNODE *>(block))->size; memptr = reinterpret_cast<char *>(block) + NODESIZE + MEM_GUARD_SIZE; for(i = 0; i < size - NODESIZE - (MEM_GUARD_SIZE * 2); i++) memptr[i] = mem_clear_string[i % mem_clear_string_len]; #endif FREE(block); }