Newer
Older
#include "config.h"
#include <iostream>
#include <map>
#ifndef MEMLEAK_CHECK_HPP
#define MEMLEAK_CHECK_HPP
typedef unsigned char * byte_ptr;
#ifdef SE_CLASS2
/////// POSSIBLE EVENTS /////////
#define VCLUSTER_EVENT 0x2001
#define VECTOR_EVENT 0x1102
#define VECTOR_STD_EVENT 0x1101
#define GRID_EVENT 0x1100
#define VECTOR_DIST_EVENT 0x4002
#define GRID_DIST_EVENT 0x4001
#define HEAPMEMORY_EVENT 0x0100
#define CUDAMEMORY_EVENT 0x0101
/////////////////////////////////
extern long int msg_on_alloc;
extern long int thr_on_alloc;
extern std::string col_stop;
extern std::map<byte_ptr,ptr_info> active_ptr;
extern long int process_v_cl;
extern long int process_to_print;
/*! \brief Check and remove the active pointer
*
* Check and remove the pointer from the active list
*
* \param pointer to check and remove
*
* \return true if the operation succeded, false if the pointer does not exist
*
*/
static bool remove_ptr(const void * ptr)
{
// Check if the pointer exist
std::map<byte_ptr, ptr_info>::iterator it = active_ptr.find((byte_ptr)ptr);
// if the element does not exist, print that something wrong happened and return
if ( it == active_ptr.end() )
{
std::cout << "Error " << __FILE__ << ":" << __LINE__ << " pointer not found " << ptr << "\n";
ACTION_ON_ERROR(MEM_ERROR);
return false;
}
// erase the pointer
active_ptr.erase((byte_ptr)ptr);
return true;
}
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#define PRJ_DEVICES 0
#define PRJ_DATA 1
#define PRJ_VCLUSTER 2
#define PRJ_IO 3
#define PRJ_PDATA 4
/*! \brief Get the color for printing unalloc pointers
*
* \param project_id id of the project
* \param size size of the allocation
* \param col color
*
*/
inline static void get_color(size_t project_id, size_t size, std::string & col)
{
if (size == 8)
{
switch (project_id)
{
case PRJ_DEVICES:
col = std::string("\e[97m");
break;
case PRJ_DATA:
col = std::string("\e[95m");
break;
case PRJ_VCLUSTER:
col = std::string("\e[96m");
break;
case PRJ_IO:
col = std::string("\e[97m");
break;
case PRJ_PDATA:
col = std::string("\e[93m");
break;
}
}
else
{
switch (project_id)
{
case PRJ_DEVICES:
col = std::string("\e[7;92m");
break;
case PRJ_DATA:
col = std::string("\e[7;95m");
break;
case PRJ_VCLUSTER:
col = std::string("\e[7;96m");
break;
case PRJ_IO:
col = std::string("\e[7;97m");
break;
case PRJ_PDATA:
col = std::string("\e[7;93m");
break;
}
}
}
/*! \brief Given the structure id it convert to a human readable structure string
*
* \param project_id id of the project
* \param prj string that identify the project
*
*/
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
inline static void get_structure(size_t struct_id, std::string & str)
{
switch (struct_id)
{
case VCLUSTER_EVENT:
str = std::string("Vcluster");
break;
case VECTOR_STD_EVENT:
str = std::string("Vector_std");
break;
case VECTOR_EVENT:
str = std::string("Vector_native");
break;
case GRID_EVENT:
str = std::string("Grid");
break;
case VECTOR_DIST_EVENT:
str = std::string("Vector distributed");
break;
case GRID_DIST_EVENT:
str = std::string("Grid distributed");
break;
case HEAPMEMORY_EVENT:
str = std::string("HeapMemory");
break;
case CUDAMEMORY_EVENT:
str = std::string("CudaMemory");
break;
default:
str = std::to_string(struct_id);
}
}
/*! \brief Given the project id it convert to a human readable project string
*
* \param project_id id of the project
* \param prj string that identify the project
*
*/
inline static void get_project(size_t project_id, std::string & prj)
{
switch (project_id)
{
case PRJ_DEVICES:
prj = std::string("devices");
break;
case PRJ_DATA:
prj = std::string("data");
break;
case PRJ_VCLUSTER:
prj = std::string("vcluster");
break;
case PRJ_IO:
prj = std::string("io");
break;
case PRJ_PDATA:
prj = std::string("pdata");
break;
}
}
std::string col;
std::string sid;
std::string prj;
for (std::map<byte_ptr,ptr_info>::iterator it = active_ptr.begin(); it != active_ptr.end(); ++it)
get_color(it->second.project_id,it->second.size,col);
get_structure(it->second.struct_id,sid);
get_project(it->second.project_id,prj);
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";
/* \brief When the allocation id==break_id is performed, print a message
*
* \param break_id
*
*/
static void message_on_alloc(long int break_id)
{
msg_on_alloc = break_id;
}
/* \brief When the allocation id==break_id is performed, throw
*
* \param throw_id
*
*/
static void throw_on_alloc(long int throw_id)
{
thr_on_alloc = throw_id;
}
/*! \brief Add the new allocated active pointer
*
* Add the new allocated active pointer
*
* \param new data active pointer
* \param sz size of the new allocated memory
*
*/
static bool check_new(const void * data, size_t sz, size_t struct_id, size_t project_id)
ptr_info & ptr = active_ptr[(byte_ptr)data];
ptr.size = sz;
ptr.id = new_data;
ptr.struct_id = struct_id;
ptr.project_id = project_id;
#ifdef SE_CLASS2_VERBOSE
if (process_to_print < 0 || process_to_print == process_v_cl)
std::cout << "New data: " << new_data << " " << data << "\n";
#endif
if (msg_on_alloc == new_data)
std::cout << "Detected allocation: " << __FILE__ << ":" << __LINE__ << " id=" << msg_on_alloc << "\n";
if (thr_on_alloc == new_data)
throw MEM_ERROR;
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
return true;
}
/*! \brief check and delete a pointer
*
* check and delete a pointer from the list of active pointers
*
* \param pointer data
* \return true if the operation to delete succeed
*
*/
static bool check_delete(const void * data)
{
if (data == NULL) return true;
// Delete the pointer
delete_data++;
bool result = remove_ptr(data);
#ifdef SE_CLASS2_VERBOSE
if (process_to_print < 0 || process_to_print == process_v_cl)
std::cout << "Delete data: " << delete_data << " " << data << "\n";
#endif
return result;
}
/*! \brief check if the access is valid
*
* check if the access is valid
*
* \param ptr pointer we are going to access
* \param size_access is the size in byte of the data we are fetching
*
* \return true if the pointer is valid
*
*/
static bool check_valid(const void * ptr, size_t size_access)
{
if (active_ptr.size() == 0)
{
std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << "\n";
ACTION_ON_ERROR(MEM_ERROR);
return false;
}
std::map<byte_ptr, ptr_info>::iterator l_b = active_ptr.upper_bound((byte_ptr)ptr);
// if there is no memory that satisfy the request
if (l_b == active_ptr.begin())
{
if (process_to_print < 0 || process_to_print == process_v_cl)
{
std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << " base allocation id=" << l_b->second.id << "\n";
ACTION_ON_ERROR(MEM_ERROR);
}
return false;
}
//! subtract one
l_b--;
// if there is no memory that satisfy the request
if (l_b == active_ptr.end())
{
if (process_to_print < 0 || process_to_print == process_v_cl)
{
std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << " base allocation id=" << l_b->second.id << "\n";
ACTION_ON_ERROR(MEM_ERROR);
}
return false;
}
// check if ptr is in the range
if (((unsigned char *)l_b->first) + sz < ((unsigned char *)ptr) + size_access)
{
if (process_to_print < 0 || process_to_print == process_v_cl)
{
std::cerr << "Error invalid pointer: " << __FILE__ << ":" << __LINE__ << " " << ptr << " base allocation id=" << l_b->second.id << "\n";
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
/*! \brief check if the access is valid
*
* check if the access is valid
*
* \param ptr pointer we are going to access
* \param size_access is the size in byte of the data we are fetching
*
* \return true if the pointer is valid
*
*/
static long int check_whoami(const void * ptr, size_t size_access)
{
if (active_ptr.size() == 0)
return -1;
// get the upper bound
std::map<byte_ptr, ptr_info>::iterator l_b = active_ptr.upper_bound((byte_ptr)ptr);
// if there is no memory that satisfy the request
if (l_b == active_ptr.begin())
return -1;
//! subtract one
l_b--;
// if there is no memory that satisfy the request
if (l_b == active_ptr.end())
return -1;
// check if ptr is in the range
size_t sz = l_b->second.size;
if (((unsigned char *)l_b->first) + sz < ((unsigned char *)ptr) + size_access)
return -1;
return l_b->second.id;
}
/*! \brief In case of Parallel application it set the process that print the
*
* \param p_to_print is < 0 (Mean all)
*
*/
static void set_process_to_print(long int p_to_print)
{
process_to_print = p_to_print;
}
#else
#endif
#endif