Debug swcsa
[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 (* volatile __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 void HeapProfiler::ResetMaxHeapConsumption() {
41     maxConsumption = 0;
42 }
43
44 unsigned long HeapProfiler::GetHeapConsumption() {
45     return consumption;
46 }
47
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;
55 }
56
57
58 void *HeapProfiler::MallocHook (size_t size, const void *caller) {
59     void *result;
60     
61     /* Restore all old hooks */
62     __malloc_hook = old_malloc_hook;
63     __free_hook = old_free_hook;
64     __realloc_hook = old_realloc_hook;
65     
66     /* Call recursively */
67     result = malloc (size);
68     
69     blocks[result] = (unsigned long)size;
70     
71     consumption += (unsigned long)size;
72     if (consumption > maxConsumption)
73         maxConsumption = consumption;
74     
75     #ifdef DEBUG_HEAPPROFILER 
76         std::cout << "malloc(" << size << ") called from " << caller << " returns " << result << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
77     #endif
78     
79     /* Save underlying hooks */
80     old_malloc_hook = __malloc_hook;
81     old_free_hook = __free_hook;
82     old_realloc_hook = __realloc_hook;
83     
84     /* Restore our own hooks */
85     __malloc_hook = HeapProfiler::MallocHook;
86     __free_hook = HeapProfiler::FreeHook;
87     __realloc_hook = HeapProfiler::ReallocHook;
88     
89     return result;
90 }
91
92 void HeapProfiler::FreeHook (void *ptr, const void *caller) {
93     
94     /* Restore all old hooks */
95     __malloc_hook = old_malloc_hook;
96     __free_hook = old_free_hook;
97     __realloc_hook = old_realloc_hook;
98      
99     /* Call recursively */
100     free (ptr);
101     
102     AllocatedBlocks::iterator result = blocks.find(ptr);
103     if (result != blocks.end())
104     {
105         #ifdef DEBUG_HEAPPROFILER 
106             std::cout << "found: " << (*result).second << std::endl;
107         #endif
108         consumption -= (*result).second;
109         blocks.erase(result);
110     } else {
111         #ifdef DEBUG_HEAPPROFILER 
112             std::cout << "not found" << std::endl;
113         #endif
114     }
115
116     #ifdef DEBUG_HEAPPROFILER
117         std::cout << "free(" << ptr << ") called from " << caller << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
118     #endif
119     
120     /* Save underlying hooks */
121     old_malloc_hook = __malloc_hook;
122     old_free_hook = __free_hook;
123     old_realloc_hook = __realloc_hook;
124         
125     /* Restore our own hooks */
126     __malloc_hook = HeapProfiler::MallocHook;
127     __free_hook = HeapProfiler::FreeHook;
128     __realloc_hook = HeapProfiler::ReallocHook;
129 }
130
131
132 void *HeapProfiler::ReallocHook (void *ptr, size_t size, const void *caller) {
133     void *newptr;
134     
135     /* Restore all old hooks */
136     __malloc_hook = old_malloc_hook;
137     __free_hook = old_free_hook;
138     __realloc_hook = old_realloc_hook;
139      
140     /* Call recursively */
141     newptr = realloc(ptr, size);
142     
143     AllocatedBlocks::iterator result = blocks.find(ptr);
144     if (result != blocks.end())
145     {
146         #ifdef DEBUG_HEAPPROFILER 
147             std::cout << "found: " << (*result).second << std::endl;
148         #endif
149         consumption -= (*result).second;
150         blocks.erase(result);
151     } else {
152         #ifdef DEBUG_HEAPPROFILER 
153             std::cout << "not found" << std::endl;
154         #endif
155     }
156     
157     blocks[newptr] = (unsigned long)size;
158     consumption += (unsigned long)size;
159     if (consumption > maxConsumption)
160         maxConsumption = consumption;
161     
162     #ifdef DEBUG_HEAPPROFILER
163         std::cout << "realloc(" << ptr << ", " << size << ") called from " << caller << ", result " << newptr << " (" << consumption << ", max " << maxConsumption << ")" << std::endl;
164     #endif
165     
166     /* Save underlying hooks */
167     old_malloc_hook = __malloc_hook;
168     old_free_hook = __free_hook;
169     old_realloc_hook = __realloc_hook;
170         
171     /* Restore our own hooks */
172     __malloc_hook = HeapProfiler::MallocHook;
173     __free_hook = HeapProfiler::FreeHook;
174     __realloc_hook = HeapProfiler::ReallocHook;
175     
176     return newptr;
177 }
178