4 #define _CRT_SECURE_NO_DEPRECATE
8#if __DCL_HAVE_ALLOC_DEBUG
19#define __strlen(s) wcslen(s)
20#define __strcpy(d, s) wcscpy(d, s)
28#define __DCL_ASSERT_N(expr)
39#define THREAD_LOCAL_STORAGE __declspec(thread)
40#elif defined(__GNUC__)
41#define THREAD_LOCAL_STORAGE __thread
44static THREAD_LOCAL_STORAGE
const char_t* __near_filename =
NULL;
45static THREAD_LOCAL_STORAGE
unsigned int __near_line = 0;
51DCLCAPI void DCLDebugAllocEnterNear(
56 __near_filename = _filename;
68 const char_t* filename = _filename;
69 if (_filename ==
NULL) {
70 filename = __near_filename;
77 __T(
"MEMDBG Warning! malloc(size:%d)!\n"), _size
89 ptr = listAlloc.allocAddTail(
101static const char_t* __AllocTypeStr(DCLAllocFunc func)
104 case DCL_ALLOC_DEFAULT :
105 return __T(
"default");
108 case DCL_ALLOC_NEW_ARRAY :
110 case DCL_ALLOC_NEW_OBJECT :
111 return __T(
"new object");
112 case DCL_ALLOC_NEW_OBJECT_ARRAY :
113 return __T(
"new[] object");
114 case DCL_ALLOC_DELETE :
115 return __T(
"delete");
116 case DCL_ALLOC_DELETE_ARRAY :
117 return __T(
"delete[]");
118 case DCL_ALLOC_DELETE_OBJECT :
119 return __T(
"delete object");
120 case DCL_ALLOC_DELETE_OBJECT_ARRAY :
121 return __T(
"delete[] object");
124 return __T(
"unknown!");
127static bool __IsValidAllocFunction(
128 DCLAllocFunc _allocType,
129 DCLAllocFunc _freeType
133 case DCL_ALLOC_DEFAULT :
134 return DCL_ALLOC_DEFAULT == _freeType;
136 return DCL_ALLOC_DELETE == _freeType;
137 case DCL_ALLOC_NEW_ARRAY :
138 return DCL_ALLOC_DELETE_ARRAY == _freeType;
139 case DCL_ALLOC_NEW_OBJECT :
140 return DCL_ALLOC_DELETE_OBJECT == _freeType;
141 case DCL_ALLOC_NEW_OBJECT_ARRAY :
142 return DCL_ALLOC_DELETE_OBJECT_ARRAY == _freeType;
144 case DCL_ALLOC_DELETE :
145 return DCL_ALLOC_NEW == _freeType;
146 case DCL_ALLOC_DELETE_ARRAY :
147 return DCL_ALLOC_NEW_ARRAY == _freeType;
148 case DCL_ALLOC_DELETE_OBJECT :
149 return DCL_ALLOC_NEW_OBJECT == _freeType;
150 case DCL_ALLOC_DELETE_OBJECT_ARRAY :
151 return DCL_ALLOC_NEW_OBJECT_ARRAY == _freeType;
166 __T(
"MEMDBG Error! free(ptr:NULL) ptr is NULL assigned!\n")
169 DCLDebugAssert(_filename, _line,
__T(
"ptr != NULL"),
__T(
"free(ptr:NULL)"));
180 AllocList::Node* node =
NULL;
187 node = listAlloc.rfind(_ptr);
189 validFunc = __IsValidAllocFunction(node->func, _func);
195 listAlloc.erase(node);
199 if (_filename ==
NULL)
200 _filename =
__T(
"delete location");
203 DCLDebugTrace(_filename, _line,
__T(
"MEMDBG Error! Cannot found prev alloc!!\n"));
205 DCLDebugTrace(_filename, _line,
206 __T(
"MEMDBG Error! No Match func!! alloc:%ls:%d:%ls ==> free:%ls\n"),
207 filename, line, __AllocTypeStr(func),
208 __AllocTypeStr(_func)
220 if ((_count == 0) || (_size == 0)) {
223 __T(
"MEMDBG Warning! calloc(count:%d, size:%d)! %ls(%d)\n"),
229 size_t total = _count * _size;
230 void* ptr = DCLDebugMalloc(
238 memset(ptr, 0, total);
250 if ((_ptr ==
NULL) || (_size == 0)) {
253 __T(
"MEMDBG Warning! realloc(ptr[%p], newsize[%zd])\n"),
260 AllocList::Node* oldNode =
NULL;
263 DCLAllocFunc oldFunc = DCL_ALLOC_DEFAULT;
270 oldNode = listAlloc.rfind(_ptr);
275 listAlloc.erase(oldNode);
278 if (oldNode->func != DCL_ALLOC_DEFAULT) {
279 __strcpy(oldFilename, oldNode->filename);
280 oldLine = oldNode->line;
281 oldFunc = oldNode->func;
285 AllocList::Node* newNode =
286 listAlloc.reallocNode(
293 newptr = newNode->data;
300 newptr = listAlloc.allocAddTail(
311 DCLDebugTrace(_filename, _line,
__T(
"MEMDBG Error! Cannot found prev alloc!!\n"));
312 else if (oldFunc != DCL_ALLOC_DEFAULT)
313 DCLDebugTrace(_filename, _line,
314 __T(
"MEMDBG Error! Invalid realloc!! prev:%ls:%d:%ls ==> realloc\n"),
315 oldFilename, oldLine, __AllocTypeStr(oldFunc)
321DCLCAPI bool DCLDebugAllocIsValid(
const void* _ptr)
329 found = listAlloc.find(_ptr) !=
NULL;
335DCLCAPI void DCLDebugAllocSetCheckFlag(
344 AllocList::Node* node = listAlloc.rfind(_ptr);
346 node->check = _check;
350DCLCAPI bool DCLDebugAllocGetPosition(
361 AllocList::Node* node = listAlloc.rfind(_ptr);
363 wcsncpy(_filename, node->filename, _buflen);
374DCLCAPI const void* DCLDebugGetLastAllocPosition(
378 const void* ptr =
NULL;
383 AllocList::Node* node = listAlloc.end();
385 if (node->thread == _thread) {
386 ptr = (
const void*)node;
390 listAlloc.prev(node);
401DCLCAPI size_t DCLDebugDumpThreadMemoryLeak(
403 const void* _startPosition,
404 DCLAllocLeakDumpLevel _level,
405 __DCL_NAMESPACE
Writer* _writer
412 AllocList::Node* startNode = listAlloc.begin();
413 AllocList::Node* node = startNode;
414 if (_startPosition) {
416 if (_startPosition == (
const void*)node) {
417 listAlloc.next(node);
421 listAlloc.next(node);
429 if (node->thread == _thread) {
432 listAlloc.next(node);
435 AllocList::Node* leeks =
NULL;
440 leeks = (AllocList::Node*) malloc(AllocList::Node::SIZE() * count);
450 if (node->thread == _thread)
451 memcpy(&leeks[i++], node, AllocList::Node::SIZE());
453 listAlloc.next(node);
465 for(
size_t i = 0; i < count; i++) {
468 case DCL_ALLOC_DUMP_ALL :
471 case DCL_ALLOC_DUMP_INTERNAL :
472 print = !(node->check);
474 case DCL_ALLOC_DUMP_USER :
482 __T(
"Thread memory leak!\n thread:%zd\n"),
489 _writer->printf(L
" %2d:%lc:%ls:%d:%ls:%zdbytes:%p\n",
491 node->check ? L
'U' : L
'I',
492 *(node->filename) ? node->filename : L
"(unknown)",
494 __AllocTypeStr(node->func),
514DCLCAPI size_t DCLDebugDumpGlobalMemoryLeak(
515 DCLAllocLeakDumpLevel _level,
516 __DCL_NAMESPACE
Writer* _writer
519 AllocList::Node* node =
NULL;
520 AllocList::Node* leeks =
NULL;
526 size_t count = listAlloc.count();
531 leeks = (AllocList::Node*)malloc(AllocList::Node::SIZE() * count);
538 node = listAlloc.begin();
541 memcpy(&leeks[i++], node, AllocList::Node::SIZE());
542 listAlloc.next(node);
554 for(
size_t i = 0; i < count; i++) {
557 case DCL_ALLOC_DUMP_ALL :
560 case DCL_ALLOC_DUMP_INTERNAL :
561 print = !(node->check);
563 case DCL_ALLOC_DUMP_USER :
570 _writer->printf(L
"Global memory leak!\n");
575 _writer->printf(L
" %2d:%zd:%lc:%ls:%d:%ls:%zdbytes:%p\n",
577 (
size_t)(node->thread),
578 node->check ? L
'U' : L
'I',
579 *(node->filename) ? node->filename : L
"(unknown)",
581 __AllocTypeStr(node->func),
612 return DCLDebugMalloc(
613 _size == 0 ? 1 : _size,
628 return DCLDebugMalloc(
629 _size == 0 ? 1 : _size,
661 DCL_ALLOC_DELETE_ARRAY,
669 __WINNT_NEW_DELETE_OVERRIDE
673DCLCAPI void*
operator new(
size_t _size)
675 void*
r = DCLDebugMalloc(
676 _size == 0 ? 1 : _size,
682#if __DCL_TRACE_INTNAL_
683 fprintf(stderr,
"%ls:%d new %zd %p\n",
684 __near_filename ? __near_filename : L
"(unknown)",
685 __near_line, _size,
r
691DCLCAPI void*
operator new[](
size_t _size)
693 void*
r = DCLDebugMalloc(
694 _size == 0 ? 1 : _size,
700#if __DCL_TRACE_INTNAL_
701 fprintf(stderr,
"%ls:%d new[] %zd %p\n",
702 __near_filename ? __near_filename : L
"(unknown)",
703 __near_line, _size,
r
709DCLCAPI void operator delete(
void* _ptr)
noexcept
711#if __DCL_TRACE_INTNAL_
712 fprintf(stderr,
"%ls:%d delete %p\n",
713 __near_filename ? __near_filename : L
"(unknown)",
717 DCLDebugFree(_ptr, DCL_ALLOC_DELETE,
NULL, 0);
720DCLCAPI void operator delete[](
void* _ptr)
noexcept
722#if __DCL_TRACE_INTNAL_
723 fprintf(stderr,
"%ls:%d delete[] %p\n",
724 __near_filename ? __near_filename : L
"(unknown)",
728 DCLDebugFree(_ptr, DCL_ALLOC_DELETE_ARRAY,
NULL, 0);
__DCL_BEGIN_NAMESPACE LibState * __LibState__
#define __DCL_ASSERT_N(expr)