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

SHOGUN Machine Learning Toolbox - Documentation