Fixed MakeStatic()
[SXSI/TextCollection.git] / HeapProfiler.cpp
1 /***************************************************************************
2  *   Installs handlers for malloc(), realloc() and free()                  *
3  *                                                                         *
4  *   Copyright (C) 2006 by Niko Välimäki                                   *
5  *                                                                         *
6  *                                                                         *
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.                                   *
11  *                                                                         *
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.                          *
16  *                                                                         *
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  ***************************************************************************/
22
23 #include "HeapProfiler.h"
24
25 // Static data
26 unsigned long HeapProfiler::consumption = 0, HeapProfiler::maxConsumption = 0;
27 AllocatedBlocks HeapProfiler::blocks;
28
29 // Override initialising hook from the C library.
30 void (*__malloc_initialize_hook) (void) = HeapProfiler::InitHooks;
31
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 *);
36
37 unsigned long HeapProfiler::GetMaxHeapConsumption() {
38     return maxConsumption;
39 }
40
41 unsigned long HeapProfiler::GetHeapConsumption() {
42     return consumption;
43 }
44
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;
52 }
53
54
55 void *HeapProfiler::MallocHook (size_t size, const void *caller) {
56     void *result;
57     
58     /* Restore all old hooks */
59     __malloc_hook = old_malloc_hook;
60     __free_hook = old_free_hook;
61     __realloc_hook = old_realloc_hook;
62     
63     /* Call recursively */
64     result = malloc (size);
65     
66     blocks[result] = (unsigned long)size;
67     
68     consumption += (unsigned long)size;
69     if (consumption > maxConsumption)
70         maxConsumption = consumption;
71     
72     #ifdef DEBUG_HEAPPROFILER 
73         std::cout << "malloc(" << size << ") called from " << caller << " returns " << result << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
74     #endif
75     
76     /* Save underlying hooks */
77     old_malloc_hook = __malloc_hook;
78     old_free_hook = __free_hook;
79     old_realloc_hook = __realloc_hook;
80     
81     /* Restore our own hooks */
82     __malloc_hook = HeapProfiler::MallocHook;
83     __free_hook = HeapProfiler::FreeHook;
84     __realloc_hook = HeapProfiler::ReallocHook;
85     
86     return result;
87 }
88
89 void HeapProfiler::FreeHook (void *ptr, const void *caller) {
90     
91     /* Restore all old hooks */
92     __malloc_hook = old_malloc_hook;
93     __free_hook = old_free_hook;
94     __realloc_hook = old_realloc_hook;
95      
96     /* Call recursively */
97     free (ptr);
98     
99     AllocatedBlocks::iterator result = blocks.find(ptr);
100     if (result != blocks.end())
101     {
102         #ifdef DEBUG_HEAPPROFILER 
103             std::cout << "found: " << (*result).second << std::endl;
104         #endif
105         consumption -= (*result).second;
106         blocks.erase(result);
107     } else {
108         #ifdef DEBUG_HEAPPROFILER 
109             std::cout << "not found" << std::endl;
110         #endif
111     }
112
113     #ifdef DEBUG_HEAPPROFILER
114         std::cout << "free(" << ptr << ") called from " << caller << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
115     #endif
116     
117     /* Save underlying hooks */
118     old_malloc_hook = __malloc_hook;
119     old_free_hook = __free_hook;
120     old_realloc_hook = __realloc_hook;
121         
122     /* Restore our own hooks */
123     __malloc_hook = HeapProfiler::MallocHook;
124     __free_hook = HeapProfiler::FreeHook;
125     __realloc_hook = HeapProfiler::ReallocHook;
126 }
127
128
129 void *HeapProfiler::ReallocHook (void *ptr, size_t size, const void *caller) {
130     void *newptr;
131     
132     /* Restore all old hooks */
133     __malloc_hook = old_malloc_hook;
134     __free_hook = old_free_hook;
135     __realloc_hook = old_realloc_hook;
136      
137     /* Call recursively */
138     newptr = realloc(ptr, size);
139     
140     AllocatedBlocks::iterator result = blocks.find(ptr);
141     if (result != blocks.end())
142     {
143         #ifdef DEBUG_HEAPPROFILER 
144             std::cout << "found: " << (*result).second << std::endl;
145         #endif
146         consumption -= (*result).second;
147         blocks.erase(result);
148     } else {
149         #ifdef DEBUG_HEAPPROFILER 
150             std::cout << "not found" << std::endl;
151         #endif
152     }
153     
154     blocks[newptr] = (unsigned long)size;
155     consumption += (unsigned long)size;
156     if (consumption > maxConsumption)
157         maxConsumption = consumption;
158     
159     #ifdef DEBUG_HEAPPROFILER
160         std::cout << "realloc(" << ptr << ", " << size << ") called from " << caller << ", result " << newptr << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
161     #endif
162     
163     /* Save underlying hooks */
164     old_malloc_hook = __malloc_hook;
165     old_free_hook = __free_hook;
166     old_realloc_hook = __realloc_hook;
167         
168     /* Restore our own hooks */
169     __malloc_hook = HeapProfiler::MallocHook;
170     __free_hook = HeapProfiler::FreeHook;
171     __realloc_hook = HeapProfiler::ReallocHook;
172     
173     return newptr;
174 }
175