SHOGUN
v3.2.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 2008-2009 Soeren Sonnenburg 00008 * Copyright (C) 2008-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00009 */ 00010 00011 #include <shogun/lib/config.h> 00012 #include <shogun/lib/ShogunException.h> 00013 #include <shogun/lib/common.h> 00014 #include <shogun/lib/Map.h> 00015 #include <shogun/lib/SGVector.h> 00016 #include <shogun/lib/SGSparseVector.h> 00017 #include <shogun/lib/SGMatrix.h> 00018 #include <shogun/base/SGObject.h> 00019 00020 #include <string.h> 00021 00022 #ifdef USE_JEMALLOC 00023 #include <jemalloc/jemalloc.h> 00024 #elif USE_TCMALLOC 00025 #include <gperftools/tcmalloc.h> 00026 #endif 00027 00028 using namespace shogun; 00029 00030 #ifdef TRACE_MEMORY_ALLOCS 00031 extern CMap<void*, shogun::MemoryBlock>* sg_mallocs; 00032 00033 MemoryBlock::MemoryBlock() : ptr(NULL), size(0), file(NULL), 00034 line(-1), is_sgobject(false) 00035 { 00036 } 00037 00038 MemoryBlock::MemoryBlock(void* p) : ptr(p), size(0), file(NULL), 00039 line(-1), is_sgobject(false) 00040 { 00041 } 00042 00043 MemoryBlock::MemoryBlock(void* p, size_t sz, const char* fname, int linenr) : 00044 ptr(p), size(sz), file(fname), line(linenr), is_sgobject(false) 00045 { 00046 } 00047 00048 MemoryBlock::MemoryBlock(const MemoryBlock &b) 00049 { 00050 ptr=b.ptr; 00051 size=b.size; 00052 file=b.file; 00053 line=b.line; 00054 is_sgobject=b.is_sgobject; 00055 } 00056 00057 00058 bool MemoryBlock::operator==(const MemoryBlock &b) const 00059 { 00060 return ptr==b.ptr; 00061 } 00062 00063 void MemoryBlock::display() 00064 { 00065 if (line!=-1) 00066 { 00067 printf("Memory block at %p of size %lld bytes (allocated in %s line %d)\n", 00068 ptr, (long long int) size, file, line); 00069 } 00070 else 00071 { 00072 if (is_sgobject) 00073 { 00074 CSGObject* obj=(CSGObject*) ptr; 00075 printf("SGObject '%s' at %p of size %lld bytes with %d ref's\n", 00076 obj->get_name(), obj, (long long int) size, obj->ref_count()); 00077 } 00078 else 00079 { 00080 printf("Object at %p of size %lld bytes\n", 00081 ptr, (long long int) size); 00082 } 00083 } 00084 } 00085 00086 void MemoryBlock::set_sgobject() 00087 { 00088 is_sgobject=true; 00089 } 00090 #endif 00091 00092 #ifdef HAVE_CXX11 00093 void* operator new(size_t size) 00094 #else 00095 void* operator new(size_t size) throw (std::bad_alloc) 00096 #endif 00097 { 00098 #if defined(USE_JEMALLOC) 00099 void *p=je_malloc(size); 00100 #elif defined(USE_TCMALLOC) 00101 void *p=tc_malloc(size); 00102 #else 00103 void *p=malloc(size); 00104 #endif 00105 00106 #ifdef TRACE_MEMORY_ALLOCS 00107 if (sg_mallocs) 00108 sg_mallocs->add(p, MemoryBlock(p,size)); 00109 #endif 00110 if (!p) 00111 { 00112 const size_t buf_len=128; 00113 char buf[buf_len]; 00114 size_t written=snprintf(buf, buf_len, 00115 "Out of memory error, tried to allocate %lld bytes using new().\n", (long long int) size); 00116 if (written<buf_len) 00117 throw ShogunException(buf); 00118 else 00119 throw ShogunException("Out of memory error using new.\n"); 00120 } 00121 00122 return p; 00123 } 00124 00125 void operator delete(void *p) throw() 00126 { 00127 #ifdef TRACE_MEMORY_ALLOCS 00128 if (sg_mallocs) 00129 sg_mallocs->remove(p); 00130 #endif 00131 00132 #if defined(USE_JEMALLOC) 00133 je_free(p); 00134 #elif defined(USE_TCMALLOC) 00135 tc_free(p); 00136 #else 00137 free(p); 00138 #endif 00139 } 00140 00141 #ifdef HAVE_CXX11 00142 void* operator new[](size_t size) 00143 #else 00144 void* operator new[](size_t size) throw(std::bad_alloc) 00145 #endif 00146 { 00147 #if defined(USE_JEMALLOC) 00148 void *p=je_malloc(size); 00149 #elif defined(USE_TCMALLOC) 00150 void *p=tc_malloc(size); 00151 #else 00152 void *p=malloc(size); 00153 #endif 00154 00155 #ifdef TRACE_MEMORY_ALLOCS 00156 if (sg_mallocs) 00157 sg_mallocs->add(p, MemoryBlock(p,size)); 00158 #endif 00159 00160 if (!p) 00161 { 00162 const size_t buf_len=128; 00163 char buf[buf_len]; 00164 size_t written=snprintf(buf, buf_len, 00165 "Out of memory error, tried to allocate %lld bytes using new[].\n", (long long int) size); 00166 if (written<buf_len) 00167 throw ShogunException(buf); 00168 else 00169 throw ShogunException("Out of memory error using new[].\n"); 00170 } 00171 00172 return p; 00173 } 00174 00175 void operator delete[](void *p) throw() 00176 { 00177 #ifdef TRACE_MEMORY_ALLOCS 00178 if (sg_mallocs) 00179 sg_mallocs->remove(p); 00180 #endif 00181 00182 #if defined(USE_JEMALLOC) 00183 je_free(p); 00184 #elif defined(USE_TCMALLOC) 00185 tc_free(p); 00186 #else 00187 free(p); 00188 #endif 00189 } 00190 00191 namespace shogun 00192 { 00193 void* sg_malloc(size_t size 00194 #ifdef TRACE_MEMORY_ALLOCS 00195 , const char* file, int line 00196 #endif 00197 ) 00198 { 00199 #if defined(USE_JEMALLOC) 00200 void* p=je_malloc(size); 00201 #elif defined(USE_TCMALLOC) 00202 void *p=tc_malloc(size); 00203 #else 00204 void* p=malloc(size); 00205 #endif 00206 #ifdef TRACE_MEMORY_ALLOCS 00207 if (sg_mallocs) 00208 sg_mallocs->add(p, MemoryBlock(p,size, file, line)); 00209 #endif 00210 00211 if (!p) 00212 { 00213 const size_t buf_len=128; 00214 char buf[buf_len]; 00215 size_t written=snprintf(buf, buf_len, 00216 "Out of memory error, tried to allocate %lld bytes using malloc.\n", (long long int) size); 00217 if (written<buf_len) 00218 throw ShogunException(buf); 00219 else 00220 throw ShogunException("Out of memory error using malloc.\n"); 00221 } 00222 00223 return p; 00224 } 00225 00226 void* sg_calloc(size_t num, size_t size 00227 #ifdef TRACE_MEMORY_ALLOCS 00228 , const char* file, int line 00229 #endif 00230 ) 00231 { 00232 #if defined(USE_JEMALLOC) 00233 void* p=je_calloc(num, size); 00234 #elif defined(USE_TCMALLOC) 00235 void* p=tc_calloc(num, size); 00236 #else 00237 void* p=calloc(num, size); 00238 #endif 00239 00240 #ifdef TRACE_MEMORY_ALLOCS 00241 if (sg_mallocs) 00242 sg_mallocs->add(p, MemoryBlock(p,size, file, line)); 00243 #endif 00244 00245 if (!p) 00246 { 00247 const size_t buf_len=128; 00248 char buf[buf_len]; 00249 size_t written=snprintf(buf, buf_len, 00250 "Out of memory error, tried to allocate %lld bytes using calloc.\n", 00251 (long long int) size); 00252 00253 if (written<buf_len) 00254 throw ShogunException(buf); 00255 else 00256 throw ShogunException("Out of memory error using calloc.\n"); 00257 } 00258 00259 return p; 00260 } 00261 00262 void sg_free(void* ptr) 00263 { 00264 #ifdef TRACE_MEMORY_ALLOCS 00265 if (sg_mallocs) 00266 sg_mallocs->remove(ptr); 00267 #endif 00268 00269 #if defined(USE_JEMALLOC) 00270 je_free(ptr); 00271 #elif defined(USE_TCMALLOC) 00272 tc_free(ptr); 00273 #else 00274 free(ptr); 00275 #endif 00276 } 00277 00278 void* sg_realloc(void* ptr, size_t size 00279 #ifdef TRACE_MEMORY_ALLOCS 00280 , const char* file, int line 00281 #endif 00282 ) 00283 { 00284 #if defined(USE_JEMALLOC) 00285 void* p=je_realloc(ptr, size); 00286 #elif defined(USE_TCMALLOC) 00287 void* p=tc_realloc(ptr, size); 00288 #else 00289 void* p=realloc(ptr, size); 00290 #endif 00291 00292 #ifdef TRACE_MEMORY_ALLOCS 00293 if (sg_mallocs) 00294 sg_mallocs->remove(ptr); 00295 00296 if (sg_mallocs) 00297 sg_mallocs->add(p, MemoryBlock(p,size, file, line)); 00298 #endif 00299 00300 if (!p && (size || !ptr)) 00301 { 00302 const size_t buf_len=128; 00303 char buf[buf_len]; 00304 size_t written=snprintf(buf, buf_len, 00305 "Out of memory error, tried to allocate %lld bytes using realloc.\n", (long long int) size); 00306 if (written<buf_len) 00307 throw ShogunException(buf); 00308 else 00309 throw ShogunException("Out of memory error using realloc.\n"); 00310 } 00311 00312 return p; 00313 } 00314 00315 #ifdef TRACE_MEMORY_ALLOCS 00316 void list_memory_allocs() 00317 { 00318 MemoryBlock* temp; 00319 if (sg_mallocs) 00320 { 00321 int32_t num=sg_mallocs->get_num_elements(); 00322 int32_t size=sg_mallocs->get_array_size(); 00323 printf("%d Blocks are allocated:\n", num); 00324 00325 00326 for (int32_t i=0; i<size; i++) 00327 { 00328 temp=sg_mallocs->get_element_ptr(i); 00329 if (temp!=NULL) 00330 temp->display(); 00331 } 00332 } 00333 } 00334 #endif 00335 00336 #ifdef TRACE_MEMORY_ALLOCS 00337 #define SG_SPECIALIZED_MALLOC(type) \ 00338 template<> type* sg_generic_malloc<type >(size_t len, const char* file, int line) \ 00339 { \ 00340 return new type[len](); \ 00341 } \ 00342 \ 00343 template<> type* sg_generic_calloc<type >(size_t len, const char* file, int line) \ 00344 { \ 00345 return new type[len](); \ 00346 } \ 00347 \ 00348 template<> type* sg_generic_realloc<type >(type* ptr, size_t old_len, size_t len, const char* file, int line) \ 00349 { \ 00350 type* new_ptr = new type[len](); \ 00351 size_t min_len=old_len; \ 00352 if (len<min_len) \ 00353 min_len=len; \ 00354 for (size_t i=0; i<min_len; i++) \ 00355 new_ptr[i]=ptr[i]; \ 00356 delete[] ptr; \ 00357 return new_ptr; \ 00358 } \ 00359 \ 00360 template<> void sg_generic_free<type >(type* ptr) \ 00361 { \ 00362 delete[] ptr; \ 00363 } 00364 00365 #else // TRACE_MEMORY_ALLOCS 00366 00367 #define SG_SPECIALIZED_MALLOC(type) \ 00368 template<> type* sg_generic_malloc<type >(size_t len) \ 00369 { \ 00370 return new type[len](); \ 00371 } \ 00372 \ 00373 template<> type* sg_generic_calloc<type >(size_t len) \ 00374 { \ 00375 return new type[len](); \ 00376 } \ 00377 \ 00378 template<> type* sg_generic_realloc<type >(type* ptr, size_t old_len, size_t len) \ 00379 { \ 00380 type* new_ptr = new type[len](); \ 00381 size_t min_len=old_len; \ 00382 if (len<min_len) \ 00383 min_len=len; \ 00384 for (size_t i=0; i<min_len; i++) \ 00385 new_ptr[i]=ptr[i]; \ 00386 delete[] ptr; \ 00387 return new_ptr; \ 00388 } \ 00389 \ 00390 template<> void sg_generic_free<type >(type* ptr) \ 00391 { \ 00392 delete[] ptr; \ 00393 } 00394 #endif // TRACE_MEMORY_ALLOCS 00395 00396 SG_SPECIALIZED_MALLOC(SGVector<bool>) 00397 SG_SPECIALIZED_MALLOC(SGVector<char>) 00398 SG_SPECIALIZED_MALLOC(SGVector<int8_t>) 00399 SG_SPECIALIZED_MALLOC(SGVector<uint8_t>) 00400 SG_SPECIALIZED_MALLOC(SGVector<int16_t>) 00401 SG_SPECIALIZED_MALLOC(SGVector<uint16_t>) 00402 SG_SPECIALIZED_MALLOC(SGVector<int32_t>) 00403 SG_SPECIALIZED_MALLOC(SGVector<uint32_t>) 00404 SG_SPECIALIZED_MALLOC(SGVector<int64_t>) 00405 SG_SPECIALIZED_MALLOC(SGVector<uint64_t>) 00406 SG_SPECIALIZED_MALLOC(SGVector<float32_t>) 00407 SG_SPECIALIZED_MALLOC(SGVector<float64_t>) 00408 SG_SPECIALIZED_MALLOC(SGVector<floatmax_t>) 00409 SG_SPECIALIZED_MALLOC(SGVector<complex128_t>) 00410 00411 SG_SPECIALIZED_MALLOC(SGSparseVector<bool>) 00412 SG_SPECIALIZED_MALLOC(SGSparseVector<char>) 00413 SG_SPECIALIZED_MALLOC(SGSparseVector<int8_t>) 00414 SG_SPECIALIZED_MALLOC(SGSparseVector<uint8_t>) 00415 SG_SPECIALIZED_MALLOC(SGSparseVector<int16_t>) 00416 SG_SPECIALIZED_MALLOC(SGSparseVector<uint16_t>) 00417 SG_SPECIALIZED_MALLOC(SGSparseVector<int32_t>) 00418 SG_SPECIALIZED_MALLOC(SGSparseVector<uint32_t>) 00419 SG_SPECIALIZED_MALLOC(SGSparseVector<int64_t>) 00420 SG_SPECIALIZED_MALLOC(SGSparseVector<uint64_t>) 00421 SG_SPECIALIZED_MALLOC(SGSparseVector<float32_t>) 00422 SG_SPECIALIZED_MALLOC(SGSparseVector<float64_t>) 00423 SG_SPECIALIZED_MALLOC(SGSparseVector<floatmax_t>) 00424 SG_SPECIALIZED_MALLOC(SGSparseVector<complex128_t>) 00425 00426 SG_SPECIALIZED_MALLOC(SGMatrix<bool>) 00427 SG_SPECIALIZED_MALLOC(SGMatrix<char>) 00428 SG_SPECIALIZED_MALLOC(SGMatrix<int8_t>) 00429 SG_SPECIALIZED_MALLOC(SGMatrix<uint8_t>) 00430 SG_SPECIALIZED_MALLOC(SGMatrix<int16_t>) 00431 SG_SPECIALIZED_MALLOC(SGMatrix<uint16_t>) 00432 SG_SPECIALIZED_MALLOC(SGMatrix<int32_t>) 00433 SG_SPECIALIZED_MALLOC(SGMatrix<uint32_t>) 00434 SG_SPECIALIZED_MALLOC(SGMatrix<int64_t>) 00435 SG_SPECIALIZED_MALLOC(SGMatrix<uint64_t>) 00436 SG_SPECIALIZED_MALLOC(SGMatrix<float32_t>) 00437 SG_SPECIALIZED_MALLOC(SGMatrix<float64_t>) 00438 SG_SPECIALIZED_MALLOC(SGMatrix<floatmax_t>) 00439 SG_SPECIALIZED_MALLOC(SGMatrix<complex128_t>) 00440 #undef SG_SPECIALIZED_MALLOC 00441 } 00442 00443 void* shogun::get_copy(void* src, size_t len) 00444 { 00445 void* copy=SG_MALLOC(uint8_t, len); 00446 memcpy(copy, src, len); 00447 return copy; 00448 } 00449 00450 char* shogun::get_strdup(const char* str) 00451 { 00452 if (!str) 00453 return NULL; 00454 00455 return (char*) get_copy((void*) str, strlen(str)+1); 00456 }