OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
Memleak_check.hpp
1 #include "config.h"
2 #include <iostream>
3 #include <map>
4 #include <iomanip>
5 
6 #ifndef MEMLEAK_CHECK_HPP
7 #define MEMLEAK_CHECK_HPP
8 
9 typedef unsigned char * byte_ptr;
10 
11 #ifdef SE_CLASS2
12 
14 
15 #define VCLUSTER_EVENT 0x2001
16 
17 #define VECTOR_EVENT 0x1102
18 #define VECTOR_STD_EVENT 0x1101
19 #define GRID_EVENT 0x1100
20 
21 #define VECTOR_DIST_EVENT 0x4002
22 #define GRID_DIST_EVENT 0x4001
23 
24 #define HEAPMEMORY_EVENT 0x0100
25 #define CUDAMEMORY_EVENT 0x0101
26 
28 
29 #include "util/se_util.hpp"
30 #include "ptr_info.hpp"
31 #include <string>
32 
33 #define MEM_ERROR_OBJECT std::runtime_error("Runtime memory error")
34 
35 extern long int msg_on_alloc;
36 extern long int msg_on_dealloc;
37 extern long int thr_on_alloc;
38 extern std::string col_stop;
39 extern long int new_data;
40 extern size_t delete_data;
41 
42 extern std::map<byte_ptr,ptr_info> active_ptr;
43 
44 extern long int process_v_cl;
45 extern long int process_to_print;
46 
56 static bool remove_ptr(const void * ptr)
57 {
58  // Check if the pointer exist
59  std::map<byte_ptr, ptr_info>::iterator it = active_ptr.find((byte_ptr)ptr);
60 
61  // if the element does not exist, print that something wrong happened and return
62  if ( it == active_ptr.end() )
63  {
64  std::cout << "Error " << __FILE__ << ":" << __LINE__ << " pointer not found " << ptr << "\n";
65  ACTION_ON_ERROR(MEM_ERROR_OBJECT);
66  return false;
67  }
68 
69  it->second.ref_id--;
70 
71  // erase the pointer
72  if (it->second.ref_id == 0)
73  active_ptr.erase((byte_ptr)ptr);
74 
75  return true;
76 }
77 
78 #define PRJ_DEVICES 0
79 #define PRJ_DATA 1
80 #define PRJ_VCLUSTER 2
81 #define PRJ_IO 3
82 #define PRJ_PDATA 4
83 
91 inline static void get_color(size_t project_id, size_t size, std::string & col)
92 {
93  if (size == 8)
94  {
95  switch (project_id)
96  {
97  case PRJ_DEVICES:
98  col = std::string("\e[97m");
99  break;
100  case PRJ_DATA:
101  col = std::string("\e[95m");
102  break;
103  case PRJ_VCLUSTER:
104  col = std::string("\e[96m");
105  break;
106  case PRJ_IO:
107  col = std::string("\e[97m");
108  break;
109  case PRJ_PDATA:
110  col = std::string("\e[93m");
111  break;
112  }
113  }
114  else
115  {
116  switch (project_id)
117  {
118  case PRJ_DEVICES:
119  col = std::string("\e[7;92m");
120  break;
121  case PRJ_DATA:
122  col = std::string("\e[7;95m");
123  break;
124  case PRJ_VCLUSTER:
125  col = std::string("\e[7;96m");
126  break;
127  case PRJ_IO:
128  col = std::string("\e[7;97m");
129  break;
130  case PRJ_PDATA:
131  col = std::string("\e[7;93m");
132  break;
133  }
134  }
135 }
136 
143 inline static void get_structure(size_t struct_id, std::string & str)
144 {
145  switch (struct_id)
146  {
147  case VCLUSTER_EVENT:
148  str = std::string("Vcluster");
149  break;
150  case VECTOR_STD_EVENT:
151  str = std::string("Vector_std");
152  break;
153  case VECTOR_EVENT:
154  str = std::string("Vector_native");
155  break;
156  case GRID_EVENT:
157  str = std::string("Grid");
158  break;
159  case VECTOR_DIST_EVENT:
160  str = std::string("Vector distributed");
161  break;
162  case GRID_DIST_EVENT:
163  str = std::string("Grid distributed");
164  break;
165  case HEAPMEMORY_EVENT:
166  str = std::string("HeapMemory");
167  break;
168  case CUDAMEMORY_EVENT:
169  str = std::string("CudaMemory");
170  break;
171  default:
172  str = std::to_string(struct_id);
173  }
174 }
175 
176 
183 inline static void get_project(size_t project_id, std::string & prj)
184 {
185  switch (project_id)
186  {
187  case PRJ_DEVICES:
188  prj = std::string("devices");
189  break;
190  case PRJ_DATA:
191  prj = std::string("data");
192  break;
193  case PRJ_VCLUSTER:
194  prj = std::string("vcluster");
195  break;
196  case PRJ_IO:
197  prj = std::string("io");
198  break;
199  case PRJ_PDATA:
200  prj = std::string("pdata");
201  break;
202  }
203 }
204 
210 inline static void print_alloc()
211 {
212  std::string col;
213  std::string sid;
214  std::string prj;
215 
216  for (std::map<byte_ptr,ptr_info>::iterator it = active_ptr.begin(); it != active_ptr.end(); ++it)
217  {
218  get_color(it->second.project_id,it->second.size,col);
219  get_structure(it->second.struct_id,sid);
220  get_project(it->second.project_id,prj);
221 
222  std::cout << col << "Allocated memory " << (void *)it->first << " size=" << it->second.size << " id=" << it->second.id << " structure id=" << std::hex << sid << std::dec << " project id=" << prj << col_stop << "\n";
223  }
224 }
225 
226 /* \brief When the allocation id==break_id is performed, print a message
227  *
228  * \param break_id
229  *
230  */
231 inline static void message_on_alloc(long int break_id)
232 {
233  msg_on_alloc = break_id;
234 }
235 
236 /* \brief When the de-allocation id==break_id is performed, print a message
237  *
238  * \param break_id
239  *
240  */
241 inline static void message_on_dealloc(long int break_id)
242 {
243  msg_on_dealloc = break_id;
244 }
245 
246 /* \brief When the allocation id==break_id is performed, throw
247  *
248  * \param throw_id
249  *
250  */
251 inline static void throw_on_alloc(long int throw_id)
252 {
253  thr_on_alloc = throw_id;
254 }
255 
264 inline static bool check_new(const void * data, size_t sz, size_t struct_id, size_t project_id)
265 {
266  // Add a new pointer
267  new_data++;
268  ptr_info & ptr = active_ptr[(byte_ptr)data];
269  if (ptr.ref_id >= 1)
270  {
271  if (sz > ptr.size) ptr.size = sz;
272  }
273  else
274  ptr.size = sz;
275  ptr.id = new_data;
276  ptr.struct_id = struct_id;
277  ptr.project_id = project_id;
278  ptr.ref_id++;
279 
280 #ifdef SE_CLASS2_VERBOSE
281  if (process_to_print < 0 || process_to_print == process_v_cl)
282  std::cout << "New data: " << new_data << " " << data << " " << ptr.size << "\n";
283 #endif
284 
285  if (msg_on_alloc == new_data)
286  std::cout << "Detected allocation: " << __FILE__ << ":" << __LINE__ << " id=" << msg_on_alloc << "\n";
287 
288  if (thr_on_alloc == new_data)
289  throw MEM_ERROR_OBJECT;
290 
291  return true;
292 }
293 
302 inline static bool check_delete(const void * data)
303 {
304  if (data == NULL) return true;
305  // Delete the pointer
306  delete_data++;
307 
308  if (msg_on_dealloc == (long int)delete_data)
309  std::cout << "Detected destruction: " << __FILE__ << ":" << __LINE__ << " id=" << msg_on_alloc << "\n";
310 
311  bool result = remove_ptr(data);
312 
313 #ifdef SE_CLASS2_VERBOSE
314  if (process_to_print < 0 || process_to_print == process_v_cl)
315  std::cout << "Delete data: " << delete_data << " " << data << "\n";
316 #endif
317 
318  return result;
319 }
320 
331 inline static bool check_valid(const void * ptr, size_t size_access)
332 {
333  if (active_ptr.size() == 0)
334  {
335  std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << "\n";
336  ACTION_ON_ERROR(MEM_ERROR_OBJECT);
337  return false;
338  }
339 
340  // get the upper bound
341 
342  std::map<byte_ptr, ptr_info>::iterator l_b = active_ptr.upper_bound((byte_ptr)ptr);
343 
344  // if there is no memory that satisfy the request
345  if (l_b == active_ptr.begin())
346  {
347  if (process_to_print < 0 || process_to_print == process_v_cl)
348  {
349  std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << " base allocation id=" << l_b->second.id << "\n";
350  ACTION_ON_ERROR(MEM_ERROR_OBJECT);
351  }
352  return false;
353  }
354 
356  l_b--;
357 
358  // if there is no memory that satisfy the request
359  if (l_b == active_ptr.end())
360  {
361  if (process_to_print < 0 || process_to_print == process_v_cl)
362  {
363  std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << " base allocation id=" << l_b->second.id << "\n";
364  ACTION_ON_ERROR(MEM_ERROR_OBJECT);
365  }
366  return false;
367  }
368 
369  // check if ptr is in the range
370 
371  size_t sz = l_b->second.size;
372 
373  if (((unsigned char *)l_b->first) + sz < ((unsigned char *)ptr) + size_access)
374  {
375  bool found = false;
376 
377  // Here we do a full search across all the registered pointers
378 
379  std::map<byte_ptr, ptr_info>::iterator fit = active_ptr.begin();
380  for(; fit != active_ptr.end(); fit++)
381  {
382  if (ptr >= fit->first && (((unsigned char *)ptr) + size_access) <= (((unsigned char *)fit->first) + fit->second.size) )
383  {
384  found = true;
385  break;
386  }
387  }
388 
389  if (found == false)
390  {
391  if (process_to_print < 0 || process_to_print == process_v_cl)
392  {
393  std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << " base allocation id=" << l_b->second.id << "\n";
394  ACTION_ON_ERROR(MEM_ERROR_OBJECT);
395  }
396  }
397  }
398 
399  return true;
400 }
401 
402 
413 inline static long int check_whoami(const void * ptr, size_t size_access)
414 {
415  if (active_ptr.size() == 0)
416  return -1;
417 
418  // get the upper bound
419 
420  std::map<byte_ptr, ptr_info>::iterator l_b = active_ptr.upper_bound((byte_ptr)ptr);
421 
422  // if there is no memory that satisfy the request
423  if (l_b == active_ptr.begin())
424  return -1;
425 
427  l_b--;
428 
429  // if there is no memory that satisfy the request
430  if (l_b == active_ptr.end())
431  return -1;
432 
433  // check if ptr is in the range
434 
435  size_t sz = l_b->second.size;
436 
437  if (((unsigned char *)l_b->first) + sz < ((unsigned char *)ptr) + size_access)
438  return -1;
439 
440  return l_b->second.id;
441 }
442 
448 inline static void set_process_to_print(long int p_to_print)
449 {
450  process_to_print = p_to_print;
451 }
452 
453 #else
454 
455 
456 
457 #endif
458 #endif