#include
#include "dbg.h"
#undef new
#undef delete
#ifndef NDEBUG
//输出调试信息
void dbgout( const char fmt, ... )
{
char str【4096】;
va_list v;
va_start( v, fmt );
vsprintf( str, fmt, v );
strcat( str, "\n" );
#ifdef _UNIX
fputs( str, stderr );
#endif
#ifdef _WIN32
::OutputDebugString( str );
#endif
}
struct alloc_node
{
alloc_node lptr; /记录申请记录节点左子树/
alloc_node rptr; /记录申请记录节点右子树/
size_t len; /申请的长度(不包括前后的保护长度)/
CPCHAR file; /申请内存的代码所在文件/
UINT line; /申请内存代码所在的行/
};
static alloc_node g_heap = NULL;/堆的申请记录树根节点/
static alloc_node g_vector_heap = NULL;/vector堆的申请记录树根节点/
// Our magic guard bytes申请内存前后加上的保护字节
static BYTE g_guard【】 =
{
0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF
};
//在堆中申请一块内存(可以申请空内存n=0)
void operator new( size_t n, CPCHAR file, UINT line )
{
BYTE pmem = NULL;
if( !n ) n = 1;/**/
alloc_node pnode = (alloc_node)malloc( n + 2sizeof(g_guard) + sizeof(alloc_node) );
if( pnode )
{
pmem = (BYTE)pnode + sizeof(alloc_node) + sizeof(g_guard);
memcpy( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) );
memset( pmem, time(NULL), n );/申请的数据空间会暂时存放分配时间/
memcpy( pmem + n, g_guard, sizeof(g_guard) );
pnode->lptr = pnode->rptr = NULL;
pnode->len = n;
pnode->file = file;
pnode->line = line;
alloc_node** ppuplink = g_heap;
alloc_node pcur = g_heap;
//按照内存分配的位置将分配记录组成二叉树,把新分配的记录放入二叉树的对应位置
while( pcur )
{
if( pnode == pcur )
{
dbgout( " FATAL: duplicate memory allocated " );/重复分配内存出错/
assert( false );
exit( -1 );
}
if( pnode [span style="color: rgba(0, 0, 0, 1)"> pcur )
{
ppuplink = pcur->lptr;
pcur = pcur->lptr;
}
else
{
ppuplink = pcur->rptr;
pcur = pcur->rptr;
}
}
ppuplink = pnode;
}
return pmem;
}
//在vector请一块内存(可以申请空内存n=0)
void operator new【】( size_t n, CPCHAR file, UINT line )
{
BYTE pmem = NULL;
if( !n ) n = 1;
alloc_node pnode = (alloc_node)malloc( n + 2sizeof(g_guard) + sizeof(alloc_node) );
if( pnode )
{
pmem = (BYTE)pnode + sizeof(alloc_node) + sizeof(g_guard);
memcpy( pmem - //代码效果参考:http://www.zidongmutanji.com/bxxx/257682.html
sizeof(g_guard), g_guard, sizeof(g_guard) );memset( pmem, time(NULL), n );
memcpy( pmem + n, g_guard, sizeof(g_guard) );
pnode->lptr = pnode->rptr = NULL;
pnode->len = n;
pnode->file = file;
pnode->line = line;
alloc_node** ppuplink = g_vector_heap;
alloc_node pcur = g_vector_heap;
while( pcur )
{
if( pnode == pcur )
{
dbgout( " FATAL: duplicate memory allocated " );
assert( false );
exit( -1 );
}
if( pnode [span style="color: rgba(0, 0, 0, 1)"> pcur )
{
ppuplink = pcur->lptr;
pcur = pcur->lptr;
}
else
{
ppuplink = pcur->rptr;
pcur = pcur->rptr;
}
}
ppuplink = pnode;
}
return pmem;
}
void operator delete( void p )
{
if( !p ) return;
if( !g_heap )
{
dbgout( " FATAL: delete with empty heap " );
assert( false );
exit( -1 );
}
alloc_node pcur = g_heap;
alloc_node** ppuplink = g_heap;
while( pcur )
{
void pcurblk = (char)pcur + sizeof(alloc_node) + sizeof(g_guard);
if( p == pcurblk )
{
BYTE pmem = (BYTE)p;
//比较申请内存的前后保护字节段是否正确
if( memcmp( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) ) != 0 ||
memcmp( pmem + pcur->len, g_guard, sizeof(g_guard) ) != 0 )
{
dbgout( "** FATAL: corrupted memory at %08X", p );
assert( false );
exit( -1 );
}
memset( pmem, time(NULL), pcur->len );
if( pcur->lptr pcur->rptr )
{
// node has both ptrs so replace it with left child and move
// right child to bottom right of left child's tree
alloc_node pend = pcur->lptr;
while( pend->rptr ) pend = pend->rptr;
ppuplink = pcur->lptr;
pend->rptr = pcur->rptr;
}
else
{
// move child up
ppuplink = (pcur->lptr) ? pcur->lptr : pcur->rptr;
}
free( pcur );
return;
}
if( p [span style="color: rgba(0, 0, 0, 1)"> pcurblk )
{
ppuplink = pcur->lptr;
pcur = pcur->lptr;
}
else
{
ppuplink = pcur->rptr;
pcur = pcur->rptr;
}
}
dbgout( "** FATAL: delete on unalloced memory " );
assert( false );
exit( -1 );
}
void operator delete【】( void p )
{
if( !p ) return;
if( !g_vector_heap )
{
dbgout( "* FATAL: delete with empty heap " );
assert( false );
exit( -1 );
}
alloc_node pcur = g_vector_heap;
alloc_node ppuplink = g_vector_heap;
while( pcur )
{
void pcurblk = (char)pcur + sizeof(alloc_node) + sizeof(g_guard);
if( p == pcurblk )
{
BYTE pmem = (BYTE)p;
if( memcmp( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) ) != 0 ||
memcmp( pmem + pcur->len, g_guard, sizeof(g_guard) ) != 0 )
{
dbgout( " FATAL: corrupted memory at %08X", p );
assert( false );
exit( -1 );
}
memset( pmem, time(NULL), pcur->len );
if( pcur->lptr pcur->rptr )
{
// node has both ptrs so replace it with left child and move
// right child to bottom right of left child's tree
alloc_node pend = pcur->lptr;
while( pend->rptr ) pend = pend->rptr;
ppuplink = pcur->lptr;
pend->rptr = pcur->rptr;
}
else
{
// move child up
ppuplink = (pcur->lptr) ? pcur->lptr : pcur->rptr;
}
free( pcur );
return;
}
if( p [span style="color: rgba(0, 0, 0, 1)"> pcurblk )
{
ppuplink = pcur->lptr;
pcur = pcur->lptr;
}
else
{
ppuplink = pcur->rptr;
pcur = pcur->rptr;
}
}
dbgout( "* FATAL: delete on unalloced memory **" );
assert( false );
exit( -1 );
}
void operator new( size_t n )
{
return ::operator new( n, "(unknown)", 0 );
}
void operator new【】( size_t n )
{
return ::operator new【】( n, "(unknown)", 0 );
}
//在内存分配树中遍历,寻找总共分配的长度
static void walk_alloc_tree( alloc_node pcur, size_t pttl )
{
if( pcur )
{
walk_alloc_tree( pcur->lptr, pttl );
dbgout( "%s(%u): %u bytes at %08X", pcur->file, pcur->line,
pcur->len, (char)pcur + sizeof(alloc_node) );
*pttl += pcur->len;
walk_alloc_tree( pcur->rptr, pttl );
}
}
//显示堆中分配的内存记录
void dump_alloc_heaps( void )
{
if( g_heap || g_vector_heap )
{
size_t ttl = 0;
dbgout( "Memory leaks detected" );
dbgout( "=====================" );
dbgout( "" );
if( g_heap )
{
dbgout( "Scalar objects" );
dbgout( "--" );
walk_alloc_tree( g_heap, ttl );
dbgout( "" );
}
if( g_vector_heap )
{
dbgout( "Vector objects" );
dbgout( "--" );
walk_alloc_tree( g_vector_heap, ttl );
dbgout( "" );
}
dbgout( "=====================" );
dbgout( "Total bytes: %u", ttl );
dbgout( "=====================" );
}
}
#endif
Rust编程语言群 1036955113
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。