aGrUM  0.16.0
debug.cpp
Go to the documentation of this file.
1 
30 #include <agrum/agrum.h>
31 
32 #include <algorithm>
33 #include <iomanip>
34 #include <iostream>
35 #include <sstream>
36 #include <string>
37 #include <vector>
38 #include <mutex>
39 
40 #ifndef DOXYGEN_SHOULD_SKIP_THIS
41 
42 # include <map>
43 
44 namespace gum {
45 
46 # ifdef GUM_DEBUG_MODE
47 
48  namespace __debug__ {
49  typedef std::map< std::string, int > DEBUG_MAP;
50 
51  static std::mutex debug_mutex;
52 
53  // this static hashtable only on debug mode.
54  static DEBUG_MAP& __sizeof() {
55  // This function is not thread-safe ! (but only in debug mode)
56  static DEBUG_MAP* sizeOf = new DEBUG_MAP();
57  return *sizeOf;
58  }
59 
60  // this static hashtable only on debug mode.
61  static DEBUG_MAP& __creation() {
62  // @todo This function is not thread-safe ! (but only in debug mode)
63  static DEBUG_MAP* creation = new DEBUG_MAP();
64  return *creation;
65  }
66 
67  static DEBUG_MAP& __deletion() {
68  // @todo This function is not thread-safe ! (but only in debug mode)
69  static DEBUG_MAP* deletion = new DEBUG_MAP();
70  return *deletion;
71  }
72 
73  std::string __getFile(const char* f) {
74  std::string s(f);
75  return s.erase(0, s.rfind("/") + 1);
76  }
77 
78  void __show_trace(const char* zeKey,
79  const char* zeFile,
80  long zeLine,
81  const char* zeMsg,
82  const void* zePtr) {
83 # ifdef GUM_DEEP_TRACE_ON
84  std::cerr << std::setw(40) << std::setfill(' ') << __getFile(zeFile) << "#"
85  << std::setfill('0') << std::setw(5) << std::dec << zeLine << " : "
86  << zeMsg << " <" << zeKey << "> [" << std::hex << zePtr << "]"
87  << std::dec << std::endl;
88 # endif // TRACE_CONSTRUCTION_ON
89  }
90 
91  void __inc_creation(const char* zeKey,
92  const char* zeFile,
93  long zeLine,
94  const char* zeMsg,
95  const void* zePtr,
96  int zeSize) {
97  debug_mutex.lock();
98  __show_trace(zeKey, zeFile, zeLine, zeMsg, zePtr);
99  __creation()[zeKey]++;
100  __sizeof()[zeKey] = zeSize;
101  debug_mutex.unlock();
102  }
103 
104  // to handle static element of agrum library
105  void __dec_creation(const char* zeKey,
106  const char* zeFile,
107  long zeLine,
108  const char* zeMsg,
109  const void* zePtr) {
110  debug_mutex.lock();
111  __show_trace(zeKey, zeFile, zeLine, zeMsg, zePtr);
112  __creation()[zeKey]--;
113  debug_mutex.unlock();
114  }
115 
116  void __inc_deletion(const char* zeKey,
117  const char* zeFile,
118  long zeLine,
119  const char* zeMsg,
120  const void* zePtr) {
121  debug_mutex.lock();
122  __show_trace(zeKey, zeFile, zeLine, zeMsg, zePtr);
123  __deletion()[zeKey]++;
124  debug_mutex.unlock();
125  }
126 
127  void __dumpObjects() {
128  Size nb_err = 0;
129  double total_size = 0.0;
130 
131  char fillChar = '_';
132  int widthColLibelle = 50;
133  int widthColSizeOf = 5;
134  int widthColItemsNumber = 8;
135 
136  std::cout << std::setfill('=') << "|" << std::setw(widthColLibelle + 2) << ""
137  << "|" << std::setw(widthColSizeOf + 4) << ""
138  << "|" << std::setw(widthColItemsNumber + 2) << ""
139  << "|" << std::setw(widthColItemsNumber + 2) << ""
140  << "|" << std::endl;
141  std::cout << std::setfill(' ') << "| " << std::left
142  << std::setw(widthColLibelle) << "Class Name" << std::right
143  << " | " << std::setw(widthColSizeOf) << "Size"
144  << " | " << std::setw(widthColItemsNumber) << "#Const"
145  << " | " << std::setw(widthColItemsNumber) << "#Dest"
146  << " |" << std::endl;
147  std::cout << std::setfill('-') << "|" << std::setw(widthColLibelle + 2) << ""
148  << "|" << std::setw(widthColSizeOf + 4) << ""
149  << "|" << std::setw(widthColItemsNumber + 2) << ""
150  << "|" << std::setw(widthColItemsNumber + 2) << ""
151  << "|" << std::endl;
152  // list of created objects
153  std::map< std::string, std::string > res;
154 
155  for (DEBUG_MAP::const_iterator xx = __creation().begin();
156  xx != __creation().end();
157  ++xx) {
158  std::stringstream stream;
159  int zeCreatedObjs = xx->second;
160  int zeDeletedObjts = -1;
161  int size = __sizeof()[xx->first];
162 
163  stream << std::setfill(fillChar = (fillChar == '_') ? ' ' : '_') << "| "
164  << std::setw(widthColLibelle) << std::left << xx->first << " | "
165  << std::right << std::setw(widthColSizeOf) << size << " o | "
166  << std::setw(widthColItemsNumber) << zeCreatedObjs << " | ";
167 
168  if (size > 0) total_size += zeCreatedObjs * (size / 1024.0);
169 
170  try {
171  zeDeletedObjts = __deletion()[xx->first];
172  stream << std::setfill(fillChar) << std::setw(widthColItemsNumber)
173  << zeDeletedObjts;
174  } catch (NotFound&) {
175  stream << std::setfill(fillChar) << std::setw(widthColItemsNumber)
176  << "?????";
177  }
178 
179  stream << " |";
180  ;
181 
182  if (zeCreatedObjs != zeDeletedObjts) {
183  nb_err += std::abs(zeDeletedObjts - zeCreatedObjs);
184  stream << "<--- failed";
185  }
186 
187  res.insert(make_pair(xx->first, stream.str()));
188  // res.push_back( stream.str() );
189  }
190 
191  // list of deleted objects, but not created (?)
192  for (DEBUG_MAP::const_iterator xx = __deletion().begin();
193  xx != __deletion().end();
194  ++xx) {
195  try {
196  __creation()[xx->first];
197  } catch (NotFound&) {
198  std::stringstream stream;
199  fillChar = (fillChar == '_') ? ' ' : '_';
200  stream << std::setfill(fillChar = (fillChar == '_') ? ' ' : '_') << "| "
201  << std::setw(widthColLibelle) << std::left << xx->first + " "
202  << " | " << std::right << std::setw(widthColSizeOf)
203  << __sizeof()[xx->first] << " o | "
204  << std::setw(widthColItemsNumber) << "?????"
205  << " | " << std::setw(widthColItemsNumber) << xx->second
206  << " |<--- failed";
207  res.insert(make_pair(xx->first, stream.str()));
208  // res.push_back( stream.str() );
209  nb_err += xx->second;
210  }
211  }
212 
213  for (const auto iter : res) {
214  std::cout << iter.second << std::endl;
215  }
216 
217  std::cout << std::setfill('-');
218 
219  std::cout << "|-" << std::setw(widthColLibelle) << ""
220  << "-|-" << std::setw(widthColSizeOf + 2) << ""
221  << "-|-" << std::setw(widthColItemsNumber) << ""
222  << "-|-" << std::setw(widthColItemsNumber) << ""
223  << "-|" << std::endl;
224 
225  std::cout << std::setfill(' ');
226 
227  if (nb_err == 0) {
228  std::cout << "| " << std::setw(widthColLibelle) << "NO MEMORY LEAK !"
229  << " | "
230  << std::setw(widthColSizeOf + widthColItemsNumber * 2 + 9) << ""
231  << "|" << std::endl;
232  } else {
233  std::cout << "| " << std::setw(widthColLibelle) << "Memory leaks found "
234  << ""
235  << " | "
236  << std::setw(widthColSizeOf + widthColItemsNumber * 2 - 6)
237  << nb_err << " object(s) "
238  << "|" << std::endl;
239  }
240 
241  std::cout << "| " << std::setw(widthColLibelle) << "total "
242  << " | " << std::fixed
243  << std::setw(widthColSizeOf + widthColItemsNumber * 2 - 4)
244  << std::setprecision(2) << total_size << " Ko "
245  << "|" << std::endl;
246 
247  std::cout << std::setfill('=') << "|" << std::setw(widthColLibelle + 2) << ""
248  << "|" << std::setw(widthColSizeOf + widthColItemsNumber * 2 + 10)
249  << ""
250  << "|" << std::endl;
251  }
252 
253  // take into account static objects in agrum (no called destructor before
254  // exit())
255  void __staticCorrections() {}
256 
257  void __atexit() {
258  __staticCorrections();
259  __dumpObjects();
260  __creation().clear();
261  __deletion().clear();
262  }
263 
264  } // namespace __debug__
265 
266 # endif // GUM_DEBUG_MODE
267 
268 } /* namespace gum */
269 
270 #endif // DOXYGEN_SHOULD_SKIP_THIS
void __atexit()
Used for debug purpose.
Definition: utils_misc.cpp:50
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48