1 /***************************************************************************
2 * Installs handlers for malloc(), realloc() and free() *
4 * Copyright (C) 2006 by Niko Välimäki *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
21 ***************************************************************************/
23 #include "HeapProfiler.h"
26 unsigned long HeapProfiler::consumption = 0, HeapProfiler::maxConsumption = 0;
27 AllocatedBlocks HeapProfiler::blocks;
29 // Override initialising hook from the C library.
30 void (* volatile __malloc_initialize_hook) (void) = HeapProfiler::InitHooks;
32 // Variables to save original hooks.
33 void *(*HeapProfiler::old_malloc_hook)(size_t, const void *);
34 void (*HeapProfiler::old_free_hook)(void *, const void *);
35 void *(*HeapProfiler::old_realloc_hook)(void *, size_t, const void *);
37 unsigned long HeapProfiler::GetMaxHeapConsumption() {
38 return maxConsumption;
40 void HeapProfiler::ResetMaxHeapConsumption() {
44 unsigned long HeapProfiler::GetHeapConsumption() {
48 void HeapProfiler::InitHooks(void) {
49 old_malloc_hook = __malloc_hook;
50 old_free_hook = __free_hook;
51 old_realloc_hook = __realloc_hook;
52 __malloc_hook = HeapProfiler::MallocHook;
53 __free_hook = HeapProfiler::FreeHook;
54 __realloc_hook = HeapProfiler::ReallocHook;
58 void *HeapProfiler::MallocHook (size_t size, const void *caller) {
61 /* Restore all old hooks */
62 __malloc_hook = old_malloc_hook;
63 __free_hook = old_free_hook;
64 __realloc_hook = old_realloc_hook;
66 /* Call recursively */
67 result = malloc (size);
69 blocks[result] = (unsigned long)size;
71 consumption += (unsigned long)size;
72 if (consumption > maxConsumption)
73 maxConsumption = consumption;
75 #ifdef DEBUG_HEAPPROFILER
76 std::cout << "malloc(" << size << ") called from " << caller << " returns " << result << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
79 /* Save underlying hooks */
80 old_malloc_hook = __malloc_hook;
81 old_free_hook = __free_hook;
82 old_realloc_hook = __realloc_hook;
84 /* Restore our own hooks */
85 __malloc_hook = HeapProfiler::MallocHook;
86 __free_hook = HeapProfiler::FreeHook;
87 __realloc_hook = HeapProfiler::ReallocHook;
92 void HeapProfiler::FreeHook (void *ptr, const void *caller) {
94 /* Restore all old hooks */
95 __malloc_hook = old_malloc_hook;
96 __free_hook = old_free_hook;
97 __realloc_hook = old_realloc_hook;
99 /* Call recursively */
102 AllocatedBlocks::iterator result = blocks.find(ptr);
103 if (result != blocks.end())
105 #ifdef DEBUG_HEAPPROFILER
106 std::cout << "found: " << (*result).second << std::endl;
108 consumption -= (*result).second;
109 blocks.erase(result);
111 #ifdef DEBUG_HEAPPROFILER
112 std::cout << "not found" << std::endl;
116 #ifdef DEBUG_HEAPPROFILER
117 std::cout << "free(" << ptr << ") called from " << caller << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
120 /* Save underlying hooks */
121 old_malloc_hook = __malloc_hook;
122 old_free_hook = __free_hook;
123 old_realloc_hook = __realloc_hook;
125 /* Restore our own hooks */
126 __malloc_hook = HeapProfiler::MallocHook;
127 __free_hook = HeapProfiler::FreeHook;
128 __realloc_hook = HeapProfiler::ReallocHook;
132 void *HeapProfiler::ReallocHook (void *ptr, size_t size, const void *caller) {
135 /* Restore all old hooks */
136 __malloc_hook = old_malloc_hook;
137 __free_hook = old_free_hook;
138 __realloc_hook = old_realloc_hook;
140 /* Call recursively */
141 newptr = realloc(ptr, size);
143 AllocatedBlocks::iterator result = blocks.find(ptr);
144 if (result != blocks.end())
146 #ifdef DEBUG_HEAPPROFILER
147 std::cout << "found: " << (*result).second << std::endl;
149 consumption -= (*result).second;
150 blocks.erase(result);
152 #ifdef DEBUG_HEAPPROFILER
153 std::cout << "not found" << std::endl;
157 blocks[newptr] = (unsigned long)size;
158 consumption += (unsigned long)size;
159 if (consumption > maxConsumption)
160 maxConsumption = consumption;
162 #ifdef DEBUG_HEAPPROFILER
163 std::cout << "realloc(" << ptr << ", " << size << ") called from " << caller << ", result " << newptr << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
166 /* Save underlying hooks */
167 old_malloc_hook = __malloc_hook;
168 old_free_hook = __free_hook;
169 old_realloc_hook = __realloc_hook;
171 /* Restore our own hooks */
172 __malloc_hook = HeapProfiler::MallocHook;
173 __free_hook = HeapProfiler::FreeHook;
174 __realloc_hook = HeapProfiler::ReallocHook;