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 (*__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;
41 unsigned long HeapProfiler::GetHeapConsumption() {
45 void HeapProfiler::InitHooks(void) {
46 old_malloc_hook = __malloc_hook;
47 old_free_hook = __free_hook;
48 old_realloc_hook = __realloc_hook;
49 __malloc_hook = HeapProfiler::MallocHook;
50 __free_hook = HeapProfiler::FreeHook;
51 __realloc_hook = HeapProfiler::ReallocHook;
55 void *HeapProfiler::MallocHook (size_t size, const void *caller) {
58 /* Restore all old hooks */
59 __malloc_hook = old_malloc_hook;
60 __free_hook = old_free_hook;
61 __realloc_hook = old_realloc_hook;
63 /* Call recursively */
64 result = malloc (size);
66 blocks[result] = (unsigned long)size;
68 consumption += (unsigned long)size;
69 if (consumption > maxConsumption)
70 maxConsumption = consumption;
72 #ifdef DEBUG_HEAPPROFILER
73 std::cout << "malloc(" << size << ") called from " << caller << " returns " << result << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
76 /* Save underlying hooks */
77 old_malloc_hook = __malloc_hook;
78 old_free_hook = __free_hook;
79 old_realloc_hook = __realloc_hook;
81 /* Restore our own hooks */
82 __malloc_hook = HeapProfiler::MallocHook;
83 __free_hook = HeapProfiler::FreeHook;
84 __realloc_hook = HeapProfiler::ReallocHook;
89 void HeapProfiler::FreeHook (void *ptr, const void *caller) {
91 /* Restore all old hooks */
92 __malloc_hook = old_malloc_hook;
93 __free_hook = old_free_hook;
94 __realloc_hook = old_realloc_hook;
96 /* Call recursively */
99 AllocatedBlocks::iterator result = blocks.find(ptr);
100 if (result != blocks.end())
102 #ifdef DEBUG_HEAPPROFILER
103 std::cout << "found: " << (*result).second << std::endl;
105 consumption -= (*result).second;
106 blocks.erase(result);
108 #ifdef DEBUG_HEAPPROFILER
109 std::cout << "not found" << std::endl;
113 #ifdef DEBUG_HEAPPROFILER
114 std::cout << "free(" << ptr << ") called from " << caller << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
117 /* Save underlying hooks */
118 old_malloc_hook = __malloc_hook;
119 old_free_hook = __free_hook;
120 old_realloc_hook = __realloc_hook;
122 /* Restore our own hooks */
123 __malloc_hook = HeapProfiler::MallocHook;
124 __free_hook = HeapProfiler::FreeHook;
125 __realloc_hook = HeapProfiler::ReallocHook;
129 void *HeapProfiler::ReallocHook (void *ptr, size_t size, const void *caller) {
132 /* Restore all old hooks */
133 __malloc_hook = old_malloc_hook;
134 __free_hook = old_free_hook;
135 __realloc_hook = old_realloc_hook;
137 /* Call recursively */
138 newptr = realloc(ptr, size);
140 AllocatedBlocks::iterator result = blocks.find(ptr);
141 if (result != blocks.end())
143 #ifdef DEBUG_HEAPPROFILER
144 std::cout << "found: " << (*result).second << std::endl;
146 consumption -= (*result).second;
147 blocks.erase(result);
149 #ifdef DEBUG_HEAPPROFILER
150 std::cout << "not found" << std::endl;
154 blocks[newptr] = (unsigned long)size;
155 consumption += (unsigned long)size;
156 if (consumption > maxConsumption)
157 maxConsumption = consumption;
159 #ifdef DEBUG_HEAPPROFILER
160 std::cout << "realloc(" << ptr << ", " << size << ") called from " << caller << ", result " << newptr << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
163 /* Save underlying hooks */
164 old_malloc_hook = __malloc_hook;
165 old_free_hook = __free_hook;
166 old_realloc_hook = __realloc_hook;
168 /* Restore our own hooks */
169 __malloc_hook = HeapProfiler::MallocHook;
170 __free_hook = HeapProfiler::FreeHook;
171 __realloc_hook = HeapProfiler::ReallocHook;