00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <fs/sys/fsMemMgr.h>
00024
00025 #include <fs/sys/fsMemMgr_NoT.h>
00026 #include <memory>
00027 #include <map>
00028 #include <fs/sys/fsMemMgr.h>
00029
00030 #if defined(UNDER_CE)
00031 # include<windows.h>
00032 #endif
00033
00034 #if (_MSC_VER >= 1400) // MSVC8
00035 # pragma warning(disable : 4996) // function was marked as deprecated
00036 #endif
00037
00038 #if defined(UNDER_CE) && defined(__STL_DEFAULT_ALLOCATOR)
00039 # define FS_MMGR_WORKAROUND1
00040 #endif
00041
00042 #if defined(FS_MMGR_ENABLE_BASIC_STATS) || defined(FS_MMGR_ENABLE_TRACKING)
00043 # define FS_MMGR_DEF_ATEXIT
00044 #endif
00045
00046
00047 #if defined(FS_MMGR_ENABLE_TRACKING) && defined(FS_MMGR_ENABLE_RTM_BREAK)
00048 # if defined(_WIN32)
00049 # if defined(UNDER_CE)
00050 # define FS_MMGR_ASSERT(exp) \
00051 { \
00052 bool bExp = (exp) ? true : false; \
00053 if(!bExp) TerminateProcess(GetCurrentProcess(), 0); \
00054 }
00055 # else
00056 # define FS_MMGR_ASSERT(exp) \
00057 { \
00058 bool bExp = (exp) ? true : false; if(!bExp) __asm int 3 \
00059 }
00060 # endif
00061 # else
00062 # define FS_MMGR_ASSERT(exp) (void(0))
00063 # endif
00064 #else
00065 # define FS_MMGR_ASSERT(exp) (void(0))
00066 #endif
00067
00068
00069
00070 namespace {
00071
00072 const char *GetModNm();
00073
00075 char g_szModNm[32] = {'\0'};
00076
00077 #if defined(FS_MMGR_DEF_ATEXIT)
00079 bool g_bAtExitSet = false;
00080 #endif
00081
00082 #if defined(FS_MMGR_ENABLE_BASIC_STATS)
00084 class Stats_t
00085 {
00086 public:
00087
00088 Stats_t() : m_nAlloc(0), m_nFree(0), m_nMax(0) {}
00089
00090 void Alloc()
00091 {
00092 ++m_nAlloc;
00093
00094
00095 const int nDelta = m_nAlloc - m_nFree;
00096 if(nDelta > m_nMax) m_nMax = nDelta;
00097 }
00098
00099 void Free() { ++m_nFree; }
00100
00101 int GetNumLeaks() const { return m_nAlloc - m_nFree; }
00102
00103 void Dump(FILE *hOut) const
00104 {
00105 int nLeaks = GetNumLeaks();
00106
00107 ::fprintf(hOut, "+--------------------------------------------+\n");
00108 ::fprintf(hOut, "| FipS' MEMORY MANAGER (basic stats) |\n");
00109 ::fprintf(hOut, "| module: %-34s |\n", GetModNm());
00110 ::fprintf(hOut, "+--------------------------------+-----------+\n");
00111 ::fprintf(hOut, "| Total number of allocations | %-9d |\n",
00112 m_nAlloc);
00113 ::fprintf(hOut, "| Total number of deallocations | %-9d |\n",
00114 m_nFree);
00115 ::fprintf(hOut, "| Max number of allocations | %-9d |\n",
00116 m_nMax);
00117 ::fprintf(hOut, "| Number of leaks | %-7d %c |\n",
00118 nLeaks, nLeaks > 0 ? '!' : ' ' );
00119 ::fprintf(hOut, "+--------------------------------+-----------+\n");
00120 }
00121
00122 private:
00123
00124 int m_nAlloc;
00125 int m_nFree;
00126 int m_nMax;
00127
00128 } g_Stats;
00129 #endif
00130
00131 #if defined(FS_MMGR_ENABLE_TRACKING)
00133 enum MemOp_e
00134 {
00135 MOP_NEW,
00136 MOP_DELETE,
00137 MOP_NEW_ARRAY,
00138 MOP_DELETE_ARRAY
00139 };
00140 #endif
00141
00142 #if defined(FS_MMGR_ENABLE_TRACKING)
00144 const char * const apszMemOpNms[] =
00145 {
00146 "new",
00147 "delete",
00148 "new []",
00149 "delete []"
00150 };
00151 #endif
00152
00153 #if defined(FS_MMGR_ENABLE_TRACKING)
00155 const MemOp_e aMemOpPrs[][2] =
00156 {
00157 { MOP_NEW, MOP_DELETE },
00158 { MOP_NEW_ARRAY, MOP_DELETE_ARRAY }
00159 };
00160 #endif
00161
00162 #if defined(FS_MMGR_ENABLE_TRACKING)
00164 void StrCpyCrp(char *pszDest, const char *pszSrc, size_t uMaxLen)
00165 {
00166 size_t uLen = ::strlen(pszSrc);
00167
00168 if(uLen > uMaxLen)
00169 {
00170 size_t uCount = uMaxLen - 2;
00171 pszDest[0] = pszDest[1] = pszDest[2] = '.';
00172 ::memcpy(pszDest + 3, pszSrc + uLen - uCount + 1, uCount);
00173 }
00174 else
00175 ::strcpy(pszDest, pszSrc);
00176
00177 }
00178 #endif
00179
00180 #if defined(FS_MMGR_ENABLE_TRACKING)
00182 class CodePos_t
00183 {
00184 public:
00185
00186 char m_szFunc[32];
00187 char m_szFile[32];
00188 int m_nLine;
00189
00190 CodePos_t() { m_szFunc[0] = m_szFile[0] = '?'; m_szFunc[1] =
00191 m_szFile[1] = '\0'; m_nLine = -1; }
00192
00193 CodePos_t(const char *pszFunc, const char *pszFile, int nLine)
00194 {
00195 *this = CodePos_t();
00196
00197 if(pszFunc) StrCpyCrp(m_szFunc, pszFunc, sizeof(m_szFunc) - 1);
00198 if(pszFile) StrCpyCrp(m_szFile, pszFile, sizeof(m_szFile) - 1);
00199
00200 m_nLine = nLine;
00201 }
00202
00203 } g_LastPos;
00204 #endif
00205
00206 #if defined(FS_MMGR_ENABLE_TRACKING)
00207 #pragma warning(push)
00208 #pragma warning(disable: 4100) // unreferenced formal parameter
00209
00210
00211
00212
00213 #if defined(FS_MMGR_WORKAROUND1)
00214
00215 template<class T>
00216 class Alloc_T
00217 {
00218 public:
00219
00220
00221 static T* allocate(size_t n)
00222 { return reinterpret_cast<T*>(::malloc(n * sizeof(T))); }
00223 static T* allocate(void)
00224 { return reinterpret_cast<T*>(::malloc(sizeof(T))); }
00225 static void deallocate(void *p, size_t n)
00226 { ::free(p); }
00227 static void deallocate(void *p)
00228 { ::free(p); }
00229 };
00230
00231 #else
00232
00233 template <class T>
00234 class Alloc_T
00235 {
00236 public:
00237
00238 typedef T value_type;
00239 typedef T* pointer;
00240 typedef const T* const_pointer;
00241 typedef T& reference;
00242 typedef const T& const_reference;
00243 typedef size_t size_type;
00244 typedef ptrdiff_t difference_type;
00245
00246 template <class U>
00247 struct rebind { typedef Alloc_T<U> other; };
00248
00249 Alloc_T() {}
00250 Alloc_T(const Alloc_T &) {}
00251 #if !defined(_MSC_VER) || _MSC_VER >= 1300
00252 template <class U>
00253 Alloc_T(const Alloc_T<U> &) {}
00254 #endif
00255 ~Alloc_T() {}
00256
00257 pointer address(reference r) const { return &r; }
00258 const_pointer address(const_reference r) const { return &r; }
00259
00260
00261 pointer allocate(size_type n, const void * = 0)
00262 { return reinterpret_cast<pointer>(::malloc(n * sizeof(T))); }
00263 void deallocate(pointer p, size_type) { ::free(p); }
00264
00265 size_type max_size() const { return size_t(-1) / sizeof(T); }
00266
00267 void construct(pointer p, const T &t) { new(p) T(t); }
00268 void destroy(pointer p) { p->~T(); }
00269 };
00270
00271 template <class T, class U>
00272 bool operator == (const Alloc_T<T> &, const Alloc_T<U> &)
00273 { return true; }
00274
00275 template <class T, class U>
00276 bool operator != (const Alloc_T<T> &LHS, const Alloc_T<U> &RHS)
00277 { return false; }
00278
00279 template <>
00280 class Alloc_T<void>
00281 {
00282 public:
00283
00284 typedef void value_type;
00285 typedef void* pointer;
00286 typedef const void* const_pointer;
00287 typedef size_t size_type;
00288 typedef ptrdiff_t difference_type;
00289
00290 template <class U>
00291 struct rebind { typedef Alloc_T<U> other; };
00292 };
00293
00294 #endif
00295
00296 #pragma warning(pop)
00297 #endif
00298
00299 #if defined(FS_MMGR_ENABLE_TRACKING)
00301 class Tracker_t
00302 {
00303 public:
00304
00305 Tracker_t() : m_nCurMem(0), m_nMaxMem(0) {}
00306
00307 void Alloc(const void *pAddr, int nSize, MemOp_e eMemOp,
00308 const CodePos_t &Pos)
00309 {
00310 FS_MMGR_ASSERT(pAddr);
00311
00312 Val_t Val(nSize, eMemOp, Pos);
00313 m_Map.insert(Pair_t(pAddr, Val));
00314 m_nCurMem += nSize;
00315
00316
00317 if(m_nCurMem > m_nMaxMem) m_nMaxMem = m_nCurMem;
00318
00319 g_LastPos = CodePos_t();
00320 }
00321
00322 void Free(const void *pAddr, MemOp_e eMemOp)
00323 {
00324 if(!pAddr)
00325 return;
00326
00327 Map_t::iterator it = m_Map.find(pAddr);
00328
00329 if(it == m_Map.end())
00330 {
00331
00332
00333 FS_MMGR_ASSERT(0);
00334 return;
00335 }
00336
00337 MemOp_e AllocMemOp = (*it).second.m_MemOp;
00338 bool bFound = false;
00339 for(int i = 0; i < sizeof(aMemOpPrs) / sizeof(aMemOpPrs[0]); ++i)
00340 if(
00341 AllocMemOp == aMemOpPrs[i][0] &&
00342 eMemOp == aMemOpPrs[i][1]
00343 )
00344 { bFound = true; break; }
00345
00346 if(!bFound)
00347 {
00348
00349
00350 FS_MMGR_ASSERT(0);
00351 return;
00352 }
00353
00354 m_nCurMem -= (*it).second.m_nSize;
00355 m_Map.erase(it);
00356 }
00357
00358 int GetNumLeaks() const { return static_cast<int>(m_Map.size()); }
00359
00360 void Dump(FILE *hOut) const
00361 {
00362 struct Local_t
00363 {
00364 static const char * DecorSize(int nSize)
00365 {
00366 static char szOut[32];
00367
00368 if(nSize >= 1E6)
00369 ::sprintf(szOut, "%.2f MB", nSize / (float)1E6);
00370 else if(nSize >= 1E3)
00371 ::sprintf(szOut, "%.2f KB", nSize / (float)1E3);
00372 else
00373 ::sprintf(szOut, "%d B", nSize);
00374
00375 return szOut;
00376 }
00377 };
00378
00379 bool bEmpty = m_Map.empty();
00380
00381 ::fprintf(hOut, "\n+------------------------------------------+\n");
00382 ::fprintf(hOut, "| FipS' MEMORY MANAGER (tracking details) |\n");
00383 ::fprintf(hOut, "| module: %-32s |\n", GetModNm());
00384 ::fprintf(hOut, "+------------------------------+-----------+\n");
00385 ::fprintf(hOut, "| Max allocated memory size | %-9s |\n",
00386 Local_t::DecorSize(m_nMaxMem));
00387 ::fprintf(hOut, "| Number of leaks | %-7d %c |\n",
00388 m_Map.size(), bEmpty ? ' ' : '!' );
00389 ::fprintf(hOut, "+------------------------------+--%c--------+",
00390 bEmpty ? '-' : '+');
00391
00392 if(bEmpty) { ::fprintf(hOut, "\n"); return; }
00393
00394 ::fprintf(hOut, "---------------------------------"
00395 "+------------+-----------+\n");
00396
00397 for(Map_t::const_iterator it = m_Map.begin();
00398 it != m_Map.end(); ++it)
00399 {
00400 const CodePos_t &Pos = (*it).second.m_Pos;
00401 ::fprintf(hOut, "| %31s | %-6d | %-31s | 0x%08x | %-9s |\n",
00402 Pos.m_szFile, Pos.m_nLine, Pos.m_szFunc, (size_t)
00403 ((*it).first.m_pAddr), Local_t::DecorSize((*it).second.m_nSize)
00404 );
00405 }
00406
00407 ::fprintf(hOut, "+---------------------------------+--------+"
00408 "---------------------------------+------------+-----------+\n");
00409 }
00410
00411 private:
00412
00413 struct KeyT_t
00414 {
00415 KeyT_t(const void *pAddr) : m_pAddr(pAddr) {}
00416 bool operator < (const KeyT_t &RHS) const
00417 { return m_pAddr < RHS.m_pAddr; }
00418
00419 const void *m_pAddr;
00420
00421 private:
00422
00423 KeyT_t();
00424 };
00425
00426 struct ValT_t
00427 {
00428 int m_nSize;
00429 MemOp_e m_MemOp;
00430 CodePos_t m_Pos;
00431
00432 ValT_t(int nSize, MemOp_e MemOp, CodePos_t Pos):
00433 m_nSize(nSize), m_MemOp(MemOp), m_Pos(Pos) {}
00434
00435 private:
00436
00437 ValT_t();
00438 };
00439
00440 #if defined(FS_MMGR_WORKAROUND1)
00441 typedef const KeyT_t Key_t;
00442 typedef const ValT_t Val_t;
00443 #else
00444 typedef KeyT_t Key_t;
00445 typedef ValT_t Val_t;
00446 #endif
00447
00448 typedef std::pair<Key_t, Val_t> Pair_t;
00449 typedef std::map<Key_t, Val_t, std::less<Key_t>, Alloc_T<Val_t> > Map_t;
00450
00451 Map_t m_Map;
00452
00453 int m_nCurMem;
00454 int m_nMaxMem;
00455
00456 } g_Tracker;
00457 #endif
00458
00459 #if defined(FS_MMGR_DEF_ATEXIT)
00460 void AtExit()
00461 {
00462 char pszFile[256];
00463
00464 #if defined(UNDER_CE)
00465
00466
00467
00468
00469 wchar_t wszTemp[MAX_PATH + 1];
00470 ::GetModuleFileName(0, wszTemp, MAX_PATH);
00471
00472 size_t i = 0; while(i < MAX_PATH) { char ch = static_cast<wchar_t>
00473 (wszTemp[i]); pszFile[i] = ch; if(ch == '\0') break; ++i; }
00474
00475 char *pszSep = ::strrchr(pszFile, '\\');
00476 FS_MMGR_ASSERT(pszSep);
00477 *(pszSep + 1) = '\0';
00478
00479 ::strcat(pszFile, "fs_mmgr_");
00480 ::strcat(pszFile, GetModNm());
00481 ::strcat(pszFile, ".log");
00482
00483 #else
00484
00485 ::sprintf(pszFile, "fs_mmgr_%s.log", GetModNm());
00486
00487 #endif
00488
00489 FILE *hOutFl = ::fopen(pszFile, "w");
00490
00491 if(!hOutFl)
00492 return;
00493
00494 bool bLeaks = false;
00495
00496 #if defined(FS_MMGR_ENABLE_BASIC_STATS)
00497 g_Stats.Dump(hOutFl);
00498 bLeaks |= g_Stats.GetNumLeaks() > 0 ? true : false;
00499 #endif
00500
00501 #if defined(FS_MMGR_ENABLE_TRACKING)
00502 g_Tracker.Dump(hOutFl);
00503 bLeaks |= g_Tracker.GetNumLeaks() > 0 ? true : false;
00504 #endif
00505
00506 ::fclose(hOutFl);
00507
00508 if(bLeaks)
00509 {
00510
00511
00512 FS_MMGR_ASSERT(0);
00513 }
00514 }
00515 #endif
00516
00517 #if defined(FS_MMGR_OWN_OPERATORS)
00518 void * Alloc(size_t uSize)
00519 {
00520 #if defined(FS_MMGR_DEF_ATEXIT)
00521 if(!g_bAtExitSet)
00522 {
00523 ::atexit(AtExit);
00524 g_bAtExitSet = true;
00525 }
00526 #endif
00527
00528 #if defined(FS_MMGR_ENABLE_BASIC_STATS)
00529 g_Stats.Alloc();
00530 #endif
00531
00532 #if defined(FS_MMGR_ENABLE_POOL)
00533 # error Not implemented!
00534 return 0;
00535 #else
00536 return ::malloc(uSize);
00537 #endif
00538 }
00539 #endif
00540
00541 #if defined(FS_MMGR_OWN_OPERATORS)
00542 void Free(void *pAddr)
00543 {
00544 #if defined(FS_MMGR_ENABLE_BASIC_STATS)
00545 g_Stats.Free();
00546 #endif
00547
00548 #if defined(FS_MMGR_ENABLE_POOL)
00549 # error Not implemented!
00550 #else
00551 ::free(pAddr);
00552 #endif
00553 }
00554 #endif
00555
00559 const char * GetModNm()
00560 {
00561 if(g_szModNm[0] == '\0')
00562 ::sprintf(g_szModNm, "0x%08x", (size_t)&GetModNm);
00563
00564 return g_szModNm;
00565 }
00566
00567 }
00568
00569
00570
00579 void fs::sys::mmgr::SetModNm(const char *pszModNm)
00580 {
00581 if(pszModNm)
00582 {
00583 ::strncpy(g_szModNm, pszModNm, sizeof(g_szModNm));
00584 g_szModNm[sizeof(g_szModNm) - 1] = '\0';
00585 }
00586 else
00587 g_szModNm[0] = '\0';
00588 }
00589
00590 #if defined(FS_MMGR_ENABLE_TRACKING)
00591 void fs::sys::mmgr::aux::Track(const char *pszFunc, const char *pszFile,
00592 int nLine)
00593 {
00594 g_LastPos = CodePos_t(pszFunc, pszFile, nLine);
00595 }
00596 #endif
00597
00598
00599
00600 #include <fs/sys/fsMemMgr_NoT.h>
00601
00602 #if defined(FS_MMGR_OWN_OPERATORS)
00603 void * operator new (size_t uSize)
00604 {
00605 void *pAddr = Alloc(uSize);
00606
00607 #if defined(FS_MMGR_ENABLE_TRACKING)
00608 g_Tracker.Alloc
00609 (pAddr, static_cast<int>(uSize), MOP_NEW, g_LastPos);
00610 #endif
00611
00612 return pAddr;
00613 }
00614 #endif
00615
00616 #if defined(FS_MMGR_OWN_OPERATORS)
00617 void operator delete (void *pAddr)
00618 {
00619 #if defined(FS_MMGR_ENABLE_TRACKING)
00620 g_Tracker.Free(pAddr, MOP_DELETE);
00621 #endif
00622
00623 Free(pAddr);
00624 }
00625 #endif
00626
00627 #if defined(FS_MMGR_OWN_OPERATORS)
00628 void * operator new [] (size_t uSize)
00629 {
00630 void *pAddr = Alloc(uSize);
00631
00632 #if defined(FS_MMGR_ENABLE_TRACKING)
00633 g_Tracker.Alloc
00634 (pAddr, static_cast<int>(uSize), MOP_NEW_ARRAY, g_LastPos);
00635 #endif
00636
00637 return pAddr;
00638 }
00639 #endif
00640
00641 #if defined(FS_MMGR_OWN_OPERATORS)
00642 void operator delete [] (void *pAddr)
00643 {
00644 #if defined(FS_MMGR_ENABLE_TRACKING)
00645 g_Tracker.Free(pAddr, MOP_DELETE_ARRAY);
00646 #endif
00647
00648 Free(pAddr);
00649 }
00650 #endif
00651
00652 #include <fs/sys/fsMemMgr.h>
00653