SHOGUN  v3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
memory.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2008-2009 Soeren Sonnenburg
8  * Copyright (C) 2008-2009 Fraunhofer Institute FIRST and Max-Planck-Society
9  */
10 
11 #include <shogun/lib/config.h>
13 #include <shogun/lib/common.h>
14 #include <shogun/lib/Map.h>
15 #include <shogun/lib/SGVector.h>
17 #include <shogun/lib/SGMatrix.h>
18 #include <shogun/base/SGObject.h>
19 
20 #include <string.h>
21 
22 #ifdef USE_JEMALLOC
23 #include <jemalloc/jemalloc.h>
24 #elif USE_TCMALLOC
25 #include <gperftools/tcmalloc.h>
26 #endif
27 
28 using namespace shogun;
29 
30 #ifdef TRACE_MEMORY_ALLOCS
31 extern CMap<void*, shogun::MemoryBlock>* sg_mallocs;
32 
33 MemoryBlock::MemoryBlock() : ptr(NULL), size(0), file(NULL),
34  line(-1), is_sgobject(false)
35 {
36 }
37 
38 MemoryBlock::MemoryBlock(void* p) : ptr(p), size(0), file(NULL),
39  line(-1), is_sgobject(false)
40 {
41 }
42 
43 MemoryBlock::MemoryBlock(void* p, size_t sz, const char* fname, int linenr) :
44  ptr(p), size(sz), file(fname), line(linenr), is_sgobject(false)
45 {
46 }
47 
48 MemoryBlock::MemoryBlock(const MemoryBlock &b)
49 {
50  ptr=b.ptr;
51  size=b.size;
52  file=b.file;
53  line=b.line;
54  is_sgobject=b.is_sgobject;
55 }
56 
57 
58 bool MemoryBlock::operator==(const MemoryBlock &b) const
59 {
60  return ptr==b.ptr;
61 }
62 
63 void MemoryBlock::display()
64 {
65  if (line!=-1)
66  {
67  printf("Memory block at %p of size %lld bytes (allocated in %s line %d)\n",
68  ptr, (long long int) size, file, line);
69  }
70  else
71  {
72  if (is_sgobject)
73  {
74  CSGObject* obj=(CSGObject*) ptr;
75  printf("SGObject '%s' at %p of size %lld bytes with %d ref's\n",
76  obj->get_name(), obj, (long long int) size, obj->ref_count());
77  }
78  else
79  {
80  printf("Object at %p of size %lld bytes\n",
81  ptr, (long long int) size);
82  }
83  }
84 }
85 
86 void MemoryBlock::set_sgobject()
87 {
88  is_sgobject=true;
89 }
90 #endif
91 
92 #ifdef HAVE_CXX11
93 void* operator new(size_t size)
94 #else
95 void* operator new(size_t size) throw (std::bad_alloc)
96 #endif
97 {
98 #if defined(USE_JEMALLOC)
99  void *p=je_malloc(size);
100 #elif defined(USE_TCMALLOC)
101  void *p=tc_malloc(size);
102 #else
103  void *p=malloc(size);
104 #endif
105 
106 #ifdef TRACE_MEMORY_ALLOCS
107  if (sg_mallocs)
108  sg_mallocs->add(p, MemoryBlock(p,size));
109 #endif
110  if (!p)
111  {
112  const size_t buf_len=128;
113  char buf[buf_len];
114  size_t written=snprintf(buf, buf_len,
115  "Out of memory error, tried to allocate %lld bytes using new().\n", (long long int) size);
116  if (written<buf_len)
117  throw ShogunException(buf);
118  else
119  throw ShogunException("Out of memory error using new.\n");
120  }
121 
122  return p;
123 }
124 
125 void operator delete(void *p) throw()
126 {
127 #ifdef TRACE_MEMORY_ALLOCS
128  if (sg_mallocs)
129  sg_mallocs->remove(p);
130 #endif
131 
132 #if defined(USE_JEMALLOC)
133  je_free(p);
134 #elif defined(USE_TCMALLOC)
135  tc_free(p);
136 #else
137  free(p);
138 #endif
139 }
140 
141 #ifdef HAVE_CXX11
142 void* operator new[](size_t size)
143 #else
144 void* operator new[](size_t size) throw(std::bad_alloc)
145 #endif
146 {
147 #if defined(USE_JEMALLOC)
148  void *p=je_malloc(size);
149 #elif defined(USE_TCMALLOC)
150  void *p=tc_malloc(size);
151 #else
152  void *p=malloc(size);
153 #endif
154 
155 #ifdef TRACE_MEMORY_ALLOCS
156  if (sg_mallocs)
157  sg_mallocs->add(p, MemoryBlock(p,size));
158 #endif
159 
160  if (!p)
161  {
162  const size_t buf_len=128;
163  char buf[buf_len];
164  size_t written=snprintf(buf, buf_len,
165  "Out of memory error, tried to allocate %lld bytes using new[].\n", (long long int) size);
166  if (written<buf_len)
167  throw ShogunException(buf);
168  else
169  throw ShogunException("Out of memory error using new[].\n");
170  }
171 
172  return p;
173 }
174 
175 void operator delete[](void *p) throw()
176 {
177 #ifdef TRACE_MEMORY_ALLOCS
178  if (sg_mallocs)
179  sg_mallocs->remove(p);
180 #endif
181 
182 #if defined(USE_JEMALLOC)
183  je_free(p);
184 #elif defined(USE_TCMALLOC)
185  tc_free(p);
186 #else
187  free(p);
188 #endif
189 }
190 
191 namespace shogun
192 {
193 void* sg_malloc(size_t size
194 #ifdef TRACE_MEMORY_ALLOCS
195  , const char* file, int line
196 #endif
197 )
198 {
199 #if defined(USE_JEMALLOC)
200  void* p=je_malloc(size);
201 #elif defined(USE_TCMALLOC)
202  void *p=tc_malloc(size);
203 #else
204  void* p=malloc(size);
205 #endif
206 #ifdef TRACE_MEMORY_ALLOCS
207  if (sg_mallocs)
208  sg_mallocs->add(p, MemoryBlock(p,size, file, line));
209 #endif
210 
211  if (!p)
212  {
213  const size_t buf_len=128;
214  char buf[buf_len];
215  size_t written=snprintf(buf, buf_len,
216  "Out of memory error, tried to allocate %lld bytes using malloc.\n", (long long int) size);
217  if (written<buf_len)
218  throw ShogunException(buf);
219  else
220  throw ShogunException("Out of memory error using malloc.\n");
221  }
222 
223  return p;
224 }
225 
226 void* sg_calloc(size_t num, size_t size
227 #ifdef TRACE_MEMORY_ALLOCS
228  , const char* file, int line
229 #endif
230 )
231 {
232 #if defined(USE_JEMALLOC)
233  void* p=je_calloc(num, size);
234 #elif defined(USE_TCMALLOC)
235  void* p=tc_calloc(num, size);
236 #else
237  void* p=calloc(num, size);
238 #endif
239 
240 #ifdef TRACE_MEMORY_ALLOCS
241  if (sg_mallocs)
242  sg_mallocs->add(p, MemoryBlock(p,size, file, line));
243 #endif
244 
245  if (!p)
246  {
247  const size_t buf_len=128;
248  char buf[buf_len];
249  size_t written=snprintf(buf, buf_len,
250  "Out of memory error, tried to allocate %lld bytes using calloc.\n",
251  (long long int) size);
252 
253  if (written<buf_len)
254  throw ShogunException(buf);
255  else
256  throw ShogunException("Out of memory error using calloc.\n");
257  }
258 
259  return p;
260 }
261 
262 void sg_free(void* ptr)
263 {
264 #ifdef TRACE_MEMORY_ALLOCS
265  if (sg_mallocs)
266  sg_mallocs->remove(ptr);
267 #endif
268 
269 #if defined(USE_JEMALLOC)
270  je_free(ptr);
271 #elif defined(USE_TCMALLOC)
272  tc_free(ptr);
273 #else
274  free(ptr);
275 #endif
276 }
277 
278 void* sg_realloc(void* ptr, size_t size
279 #ifdef TRACE_MEMORY_ALLOCS
280  , const char* file, int line
281 #endif
282 )
283 {
284 #if defined(USE_JEMALLOC)
285  void* p=je_realloc(ptr, size);
286 #elif defined(USE_TCMALLOC)
287  void* p=tc_realloc(ptr, size);
288 #else
289  void* p=realloc(ptr, size);
290 #endif
291 
292 #ifdef TRACE_MEMORY_ALLOCS
293  if (sg_mallocs)
294  sg_mallocs->remove(ptr);
295 
296  if (sg_mallocs)
297  sg_mallocs->add(p, MemoryBlock(p,size, file, line));
298 #endif
299 
300  if (!p && (size || !ptr))
301  {
302  const size_t buf_len=128;
303  char buf[buf_len];
304  size_t written=snprintf(buf, buf_len,
305  "Out of memory error, tried to allocate %lld bytes using realloc.\n", (long long int) size);
306  if (written<buf_len)
307  throw ShogunException(buf);
308  else
309  throw ShogunException("Out of memory error using realloc.\n");
310  }
311 
312  return p;
313 }
314 
315 #ifdef TRACE_MEMORY_ALLOCS
316 void list_memory_allocs()
317 {
318  MemoryBlock* temp;
319  if (sg_mallocs)
320  {
321  int32_t num=sg_mallocs->get_num_elements();
322  int32_t size=sg_mallocs->get_array_size();
323  printf("%d Blocks are allocated:\n", num);
324 
325 
326  for (int32_t i=0; i<size; i++)
327  {
328  temp=sg_mallocs->get_element_ptr(i);
329  if (temp!=NULL)
330  temp->display();
331  }
332  }
333 }
334 #endif
335 
336 #ifdef TRACE_MEMORY_ALLOCS
337 #define SG_SPECIALIZED_MALLOC(type) \
338 template<> type* sg_generic_malloc<type >(size_t len, const char* file, int line) \
339 { \
340  return new type[len](); \
341 } \
342  \
343 template<> type* sg_generic_calloc<type >(size_t len, const char* file, int line) \
344 { \
345  return new type[len](); \
346 } \
347  \
348 template<> type* sg_generic_realloc<type >(type* ptr, size_t old_len, size_t len, const char* file, int line) \
349 { \
350  type* new_ptr = new type[len](); \
351  size_t min_len=old_len; \
352  if (len<min_len) \
353  min_len=len; \
354  for (size_t i=0; i<min_len; i++) \
355  new_ptr[i]=ptr[i]; \
356  delete[] ptr; \
357  return new_ptr; \
358 } \
359  \
360 template<> void sg_generic_free<type >(type* ptr) \
361 { \
362  delete[] ptr; \
363 }
364 
365 #else // TRACE_MEMORY_ALLOCS
366 
367 #define SG_SPECIALIZED_MALLOC(type) \
368 template<> type* sg_generic_malloc<type >(size_t len) \
369 { \
370  return new type[len](); \
371 } \
372  \
373 template<> type* sg_generic_calloc<type >(size_t len) \
374 { \
375  return new type[len](); \
376 } \
377  \
378 template<> type* sg_generic_realloc<type >(type* ptr, size_t old_len, size_t len) \
379 { \
380  type* new_ptr = new type[len](); \
381  size_t min_len=old_len; \
382  if (len<min_len) \
383  min_len=len; \
384  for (size_t i=0; i<min_len; i++) \
385  new_ptr[i]=ptr[i]; \
386  delete[] ptr; \
387  return new_ptr; \
388 } \
389  \
390 template<> void sg_generic_free<type >(type* ptr) \
391 { \
392  delete[] ptr; \
393 }
394 #endif // TRACE_MEMORY_ALLOCS
395 
410 
425 
440 #undef SG_SPECIALIZED_MALLOC
441 }
442 
443 void* shogun::get_copy(void* src, size_t len)
444 {
445  void* copy=SG_MALLOC(uint8_t, len);
446  memcpy(copy, src, len);
447  return copy;
448 }
449 
450 char* shogun::get_strdup(const char* str)
451 {
452  if (!str)
453  return NULL;
454 
455  return (char*) get_copy((void*) str, strlen(str)+1);
456 }

SHOGUN Machine Learning Toolbox - Documentation