1#define _CRT_SECURE_NO_DEPRECATE
8#if __DCL_HAVE_ALLOC_DEBUG
20#define __strlen(s) wcslen(s)
21#define __strcpy(d, s) wcscpy(d, s)
33#define __DCL_ASSERT_N(expr)
44#define THREAD_LOCAL_STORAGE __declspec(thread)
45#elif defined(__GNUC__)
46#define THREAD_LOCAL_STORAGE __thread
49static THREAD_LOCAL_STORAGE
const char_t* __near_filename =
NULL;
50static THREAD_LOCAL_STORAGE
unsigned int __near_line = 0;
56DCLCAPI void DCLDebugAllocEnterNear(
61 __near_filename = _filename;
78 DCLAllocFunction allocFunction,
83 if (_filename ==
NULL) {
84 _filename = __near_filename;
92 __T(
"MEMDBG Warning! malloc(size:%d)!\n"), _size
105 p = listAlloc.allocAddTail(
118static const char_t* __AllocTypeStr(DCLAllocFunction allocFunction)
120 switch(allocFunction)
122 case DCL_ALLOC_DEFAULT :
123 return __T(
"default");
126 case DCL_ALLOC_NEW_ARRAY :
128 case DCL_ALLOC_NEW_OBJECT :
129 return __T(
"new object");
130 case DCL_ALLOC_NEW_OBJECT_ARRAY :
131 return __T(
"new[] object");
132 case DCL_ALLOC_DELETE :
133 return __T(
"delete");
134 case DCL_ALLOC_DELETE_ARRAY :
135 return __T(
"delete[]");
136 case DCL_ALLOC_DELETE_OBJECT :
137 return __T(
"delete object");
138 case DCL_ALLOC_DELETE_OBJECT_ARRAY :
139 return __T(
"delete[] object");
142 return __T(
"unknown!");
145static bool __IsValidAllocFunction(
146 DCLAllocFunction allocType,
147 DCLAllocFunction freeType
152 case DCL_ALLOC_DEFAULT :
153 return DCL_ALLOC_DEFAULT == freeType;
155 return DCL_ALLOC_DELETE == freeType;
156 case DCL_ALLOC_NEW_ARRAY :
157 return DCL_ALLOC_DELETE_ARRAY == freeType;
158 case DCL_ALLOC_NEW_OBJECT :
159 return DCL_ALLOC_DELETE_OBJECT == freeType;
160 case DCL_ALLOC_NEW_OBJECT_ARRAY :
161 return DCL_ALLOC_DELETE_OBJECT_ARRAY == freeType;
163 case DCL_ALLOC_DELETE :
164 return DCL_ALLOC_NEW == freeType;
165 case DCL_ALLOC_DELETE_ARRAY :
166 return DCL_ALLOC_NEW_ARRAY == freeType;
167 case DCL_ALLOC_DELETE_OBJECT :
168 return DCL_ALLOC_NEW_OBJECT == freeType;
169 case DCL_ALLOC_DELETE_OBJECT_ARRAY :
170 return DCL_ALLOC_NEW_OBJECT_ARRAY == freeType;
177 DCLAllocFunction allocFunction,
186 __T(
"MEMDBG Error! free(p:NULL) p is NULL assigned!\n")
189 DCLDebugAssert(__filename, __line,
__T(
"p != NULL"),
__T(
"free(p:NULL)"));
200 AllocList::Node* pNode =
NULL;
207 pNode = listAlloc.rfind(__p);
210 bValidFunction = __IsValidAllocFunction(pNode->allocFunction, allocFunction);
213 __strcpy(szAllocFile, pNode->szFileName);
214 nAllocLine = pNode->nLine;
215 af = pNode->allocFunction;
217 listAlloc.erase(pNode);
221 if (__filename ==
NULL)
222 __filename =
__T(
"delete location");
225 DCLDebugTrace(__filename, __line,
__T(
"MEMDBG Error! Cannot found prev alloc!!\n"));
226 else if (!bValidFunction)
227 DCLDebugTrace(__filename, __line,
228 __T(
"MEMDBG Error! No Match allocFunction!! alloc:%ls:%d:%ls ==> free:%ls\n"),
229 szAllocFile, nAllocLine, __AllocTypeStr(af),
230 __AllocTypeStr(allocFunction)
242 if ((__count == 0) || (_size == 0))
246 __T(
"MEMDBG Warning! calloc(count:%d, size:%d)! %ls(%d)\n"),
252 size_t nTotalSize = __count * _size;
254 void*
result = DCLDebugMalloc(
262 memset(
result, 0, nTotalSize);
274 if ((__oldptr ==
NULL) || (__newsize == 0))
278 __T(
"MEMDBG Warning! realloc(oldptr:%p, newsize:%d)\n"),
286 AllocList::Node* pOldNode =
NULL;
287 char_t szOldFileName[512];
289 DCLAllocFunction oldAF = DCL_ALLOC_DEFAULT;
298 pOldNode = listAlloc.rfind(__oldptr);
305 listAlloc.erase(pOldNode);
309 if (pOldNode->allocFunction != DCL_ALLOC_DEFAULT)
311 __strcpy(szOldFileName, pOldNode->szFileName);
312 nOldLine = pOldNode->nLine;
313 oldAF = pOldNode->allocFunction;
319 AllocList::Node* pNewNode =
320 listAlloc.reallocNode(
327 newptr = pNewNode->data();
335 newptr = listAlloc.allocAddTail(
346 if (pOldNode ==
NULL)
347 DCLDebugTrace(__filename, __line,
__T(
"MEMDBG Error! Cannot found prev alloc!!\n"));
348 else if (oldAF != DCL_ALLOC_DEFAULT)
349 DCLDebugTrace(__filename, __line,
350 __T(
"MEMDBG Error! Invalid realloc!! prev:%ls:%d:%ls ==> realloc\n"),
351 szOldFileName, nOldLine, __AllocTypeStr(oldAF)
357DCLCAPI bool DCLDebugAllocIsValid(
const void* _ptr)
365 bFound = listAlloc.find(_ptr) !=
NULL;
371DCLCAPI void DCLDebugAllocSetCheckFlag(
380 AllocList::Node* pNode = listAlloc.rfind(_ptr);
382 pNode->bCheck = _check;
386DCLCAPI bool DCLDebugAllocGetPosition(
397 AllocList::Node* pNode = listAlloc.rfind(_ptr);
399 wcsncpy(_pfilename, pNode->szFileName, _count);
400 *_pline = pNode->nLine;
404 return pNode !=
NULL;
410DCLCAPI const void* DCLDebugGetLastAllocPosition(
411 unsigned long uThreadId
414 const void* pv =
NULL;
420 AllocList::Node* pNode = listAlloc.end();
423 if (pNode->uThreadId == uThreadId)
425 pv = (
const void*)pNode;
429 listAlloc.prev(pNode);
440DCLCAPI size_t DCLDebugDumpThreadMemoryLeak(
441 unsigned long uThreadId,
442 const void* pvStartPosition,
443 DCLAllocLeakDumpLevel level,
444 __DCL_NAMESPACE
Writer* pWriter
452 AllocList::Node* pStartNode = listAlloc.begin();
453 AllocList::Node* pNode = pStartNode;
458 if (pvStartPosition == (
const void*)pNode)
460 listAlloc.next(pNode);
464 listAlloc.next(pNode);
474 if (pNode->uThreadId == uThreadId)
478 listAlloc.next(pNode);
481 AllocList::Node* pLeaks =
NULL;
487 pLeaks = (AllocList::Node*) malloc(
sizeof(AllocList::Node) * nCount);
499 if (pNode->uThreadId == uThreadId)
500 memcpy(&pLeaks[i++], pNode,
sizeof(AllocList::Node));
502 listAlloc.next(pNode);
512 bool bHeaderPrint =
false;
513 bool bDoPrint =
false;
516 for(
size_t i = 0; i < nCount; i++)
521 case DCL_ALLOC_DUMP_ALL :
524 case DCL_ALLOC_DUMP_INTERNAL :
525 bDoPrint = !(pNode->bCheck);
527 case DCL_ALLOC_DUMP_USER :
528 bDoPrint = pNode->bCheck;
536 pWriter->printf(
__T(
"Thread memory leak!\n thread:%u\n"), uThreadId);
542 pWriter->printf(L
" %2d:%lc:%ls:%d:%ls:%zdbytes:%p\n",
544 pNode->bCheck ? L
'U' : L
'I',
545 *(pNode->szFileName) ? pNode->szFileName : L
"(unknown)",
547 __AllocTypeStr(pNode->allocFunction),
568DCLCAPI size_t DCLDebugDumpGlobalMemoryLeak(
569 DCLAllocLeakDumpLevel level,
570 __DCL_NAMESPACE
Writer* pWriter
573 AllocList::Node* pNode =
NULL;
574 AllocList::Node* pLeaks =
NULL;
580 size_t nCount = listAlloc.count();
586 pLeaks = (AllocList::Node*)malloc(
sizeof(AllocList::Node) * nCount);
594 pNode = listAlloc.begin();
598 memcpy(&pLeaks[i++], pNode,
sizeof(AllocList::Node));
600 listAlloc.next(pNode);
610 bool bHeaderPrint =
false;
611 bool bDoPrint =
false;
614 for(
size_t i = 0; i < nCount; i++)
619 case DCL_ALLOC_DUMP_ALL :
622 case DCL_ALLOC_DUMP_INTERNAL :
623 bDoPrint = !(pNode->bCheck);
625 case DCL_ALLOC_DUMP_USER :
626 bDoPrint = pNode->bCheck;
634 pWriter->printf(L
"Global memory leak!\n");
640 pWriter->printf(L
" %2d:%u:%lc:%ls:%d:%ls:%zdbytes:%p\n",
643 pNode->bCheck ? L
'U' : L
'I',
644 *(pNode->szFileName) ? pNode->szFileName : L
"(unknown)",
646 __AllocTypeStr(pNode->allocFunction),
678 return DCLDebugMalloc(
679 _size == 0 ? 1 : _size,
694 return DCLDebugMalloc(
695 _size == 0 ? 1 : _size,
728 DCL_ALLOC_DELETE_ARRAY,
741DCLCAPI void*
operator new(
size_t _size)
743 void*
r = DCLDebugMalloc(
744 _size == 0 ? 1 : _size,
756DCLCAPI void*
operator new[](
size_t _size)
758 void*
r = DCLDebugMalloc(
759 _size == 0 ? 1 : _size,
771DCLCAPI void operator delete(
void* _ptr)
776 DCLDebugFree(_ptr, DCL_ALLOC_DELETE,
NULL, 0);
779DCLCAPI void operator delete[](
void* _ptr)
784 DCLDebugFree(_ptr, DCL_ALLOC_DELETE_ARRAY,
NULL, 0);
__DCL_BEGIN_NAMESPACE LibState * __pLibState
#define __DCL_ASSERT_N(expr)
#define __DCL_TRACE0(psz)