mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 02:49:21 +02:00
+ added trace of first dispose for errors
This commit is contained in:
parent
fb43998d8c
commit
0bccbc5fde
@ -19,15 +19,22 @@ interface
|
|||||||
procedure dump_heap;
|
procedure dump_heap;
|
||||||
procedure mark_heap;
|
procedure mark_heap;
|
||||||
|
|
||||||
|
const
|
||||||
|
tracesize = 8;
|
||||||
|
quicktrace : boolean=true;
|
||||||
|
keepreleased : boolean=true;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
const
|
|
||||||
tracesize = 4;
|
|
||||||
quicktrace : boolean=true;
|
|
||||||
|
|
||||||
type
|
type
|
||||||
pheap_mem_info = ^theap_mem_info;
|
pheap_mem_info = ^theap_mem_info;
|
||||||
|
{ warning the size of theap_mem_info
|
||||||
|
must be a multiple of 8
|
||||||
|
because otherwise you will get
|
||||||
|
problems when releasing the usual memory part !!
|
||||||
|
sizeof(theap_mem_info = 16+tracesize*4 so
|
||||||
|
tracesize must be even !! PM }
|
||||||
theap_mem_info = record
|
theap_mem_info = record
|
||||||
next,
|
next,
|
||||||
previous : pheap_mem_info;
|
previous : pheap_mem_info;
|
||||||
@ -40,28 +47,52 @@ var
|
|||||||
heap_mem_root : pheap_mem_info;
|
heap_mem_root : pheap_mem_info;
|
||||||
getmem_cnt,
|
getmem_cnt,
|
||||||
freemem_cnt : longint;
|
freemem_cnt : longint;
|
||||||
|
getmem_size,
|
||||||
|
freemem_size : longint;
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
Helpers
|
Helpers
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
procedure call_stack(p : pointer);
|
procedure call_stack(pp : pheap_mem_info);
|
||||||
var
|
var
|
||||||
i : longint;
|
i : longint;
|
||||||
pp : pheap_mem_info;
|
|
||||||
begin
|
begin
|
||||||
pp:=pheap_mem_info(p-sizeof(theap_mem_info));
|
writeln(stderr,'Call trace for block 0x',hexstr(longint(pp+sizeof(theap_mem_info)),8),' size ',pp^.size);
|
||||||
writeln(stderr,'Call trace for block 0x',hexstr(longint(p),8),' size ',pp^.size);
|
|
||||||
for i:=1 to tracesize do
|
for i:=1 to tracesize do
|
||||||
writeln(stderr,i,' 0x',hexstr(pp^.calls[i],8));
|
if pp^.calls[i]<>0 then
|
||||||
|
writeln(stderr,' 0x',hexstr(pp^.calls[i],8));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure call_free_stack(pp : pheap_mem_info);
|
||||||
|
var
|
||||||
|
i : longint;
|
||||||
|
|
||||||
|
begin
|
||||||
|
writeln(stderr,'Call trace for block 0x',hexstr(longint(pp+sizeof(theap_mem_info)),8),' size ',pp^.size);
|
||||||
|
for i:=1 to tracesize div 2 do
|
||||||
|
if pp^.calls[i]<>0 then
|
||||||
|
writeln(stderr,' 0x',hexstr(pp^.calls[i],8));
|
||||||
|
writeln(stderr,' was released at ');
|
||||||
|
for i:=(tracesize div 2)+1 to tracesize do
|
||||||
|
if pp^.calls[i]<>0 then
|
||||||
|
writeln(stderr,' 0x',hexstr(pp^.calls[i],8));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure dump_free(p : pheap_mem_info);
|
procedure dump_already_free(p : pheap_mem_info);
|
||||||
begin
|
begin
|
||||||
Writeln(stderr,'Marked memory at ',HexStr(longint(p),8),' released');
|
Writeln(stderr,'Marked memory at ',HexStr(longint(p+sizeof(theap_mem_info)),8),' released');
|
||||||
call_stack(p+sizeof(theap_mem_info));
|
call_free_stack(p);
|
||||||
|
Writeln(stderr,'freed again at');
|
||||||
|
dump_stack(get_caller_frame(get_frame));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure dump_error(p : pheap_mem_info);
|
||||||
|
begin
|
||||||
|
Writeln(stderr,'Marked memory at ',HexStr(longint(p+sizeof(theap_mem_info)),8),' invalid');
|
||||||
|
Writeln(stderr,'Wrong signature $',hexstr(p^.sig,8));
|
||||||
dump_stack(get_caller_frame(get_frame));
|
dump_stack(get_caller_frame(get_frame));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -99,6 +130,7 @@ procedure TraceGetMem(var p:pointer;size:longint);
|
|||||||
var
|
var
|
||||||
i,bp : longint;
|
i,bp : longint;
|
||||||
begin
|
begin
|
||||||
|
inc(getmem_size,size);
|
||||||
{ Do the real GetMem, but alloc also for the info block }
|
{ Do the real GetMem, but alloc also for the info block }
|
||||||
SysGetMem(p,size+sizeof(theap_mem_info));
|
SysGetMem(p,size+sizeof(theap_mem_info));
|
||||||
{ Create the info block }
|
{ Create the info block }
|
||||||
@ -127,20 +159,47 @@ end;
|
|||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
procedure TraceFreeMem(var p:pointer;size:longint);
|
procedure TraceFreeMem(var p:pointer;size:longint);
|
||||||
|
|
||||||
|
var i,bp : longint;
|
||||||
|
pp : pheap_mem_info;
|
||||||
begin
|
begin
|
||||||
|
inc(freemem_size,size);
|
||||||
inc(size,sizeof(theap_mem_info));
|
inc(size,sizeof(theap_mem_info));
|
||||||
dec(p,sizeof(theap_mem_info));
|
dec(p,sizeof(theap_mem_info));
|
||||||
|
pp:=pheap_mem_info(p);
|
||||||
if not quicktrace and not(is_in_getmem_list(p)) then
|
if not quicktrace and not(is_in_getmem_list(p)) then
|
||||||
RunError(204);
|
RunError(204);
|
||||||
if pheap_mem_info(p)^.sig=$AAAAAAAA then
|
if pp^.sig=$AAAAAAAA then
|
||||||
dump_free(p);
|
dump_already_free(pp)
|
||||||
if pheap_mem_info(p)^.next<>nil then
|
else if pp^.sig<>$DEADBEEF then
|
||||||
pheap_mem_info(p)^.next^.previous:=pheap_mem_info(p)^.previous;
|
begin
|
||||||
if pheap_mem_info(p)^.previous<>nil then
|
dump_error(pp);
|
||||||
pheap_mem_info(p)^.previous^.next:=pheap_mem_info(p)^.next;
|
{ don't release anything in this case !! }
|
||||||
if pheap_mem_info(p)=heap_mem_root then
|
exit;
|
||||||
heap_mem_root:=heap_mem_root^.previous;
|
end;
|
||||||
|
{ now it is released !! }
|
||||||
|
pp^.sig:=$AAAAAAAA;
|
||||||
|
if not keepreleased then
|
||||||
|
begin
|
||||||
|
if pp^.next<>nil then
|
||||||
|
pp^.next^.previous:=pp^.previous;
|
||||||
|
if pp^.previous<>nil then
|
||||||
|
pp^.previous^.next:=pp^.next;
|
||||||
|
if pp=heap_mem_root then
|
||||||
|
heap_mem_root:=heap_mem_root^.previous;
|
||||||
|
end;
|
||||||
|
bp:=get_caller_frame(get_frame);
|
||||||
|
for i:=(tracesize div 2)+1 to tracesize do
|
||||||
|
begin
|
||||||
|
pp^.calls[i]:=get_caller_addr(bp);
|
||||||
|
bp:=get_caller_frame(bp);
|
||||||
|
end;
|
||||||
inc(freemem_cnt);
|
inc(freemem_cnt);
|
||||||
|
{ release the normal memory at least !! }
|
||||||
|
{ this way we keep all info about all released memory !! }
|
||||||
|
dec(size,sizeof(theap_mem_info));
|
||||||
|
inc(p,sizeof(theap_mem_info));
|
||||||
|
SysFreeMem(p,size);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -151,11 +210,30 @@ end;
|
|||||||
procedure dump_heap;
|
procedure dump_heap;
|
||||||
var
|
var
|
||||||
pp : pheap_mem_info;
|
pp : pheap_mem_info;
|
||||||
|
i : longint;
|
||||||
begin
|
begin
|
||||||
pp:=heap_mem_root;
|
pp:=heap_mem_root;
|
||||||
|
Writeln(stderr,'Heap dump by heaptrc unit');
|
||||||
|
Writeln(stderr,getmem_cnt,' memory blocks allocated : ',getmem_size);
|
||||||
|
Writeln(stderr,freemem_cnt,' memory blocks allocated : ',freemem_size);
|
||||||
|
Writeln(stderr,'Unfreed memory size : ',getmem_size-freemem_size);
|
||||||
|
i:=getmem_cnt-freemem_cnt;
|
||||||
while pp<>nil do
|
while pp<>nil do
|
||||||
begin
|
begin
|
||||||
call_stack(pp+sizeof(theap_mem_info));
|
if i<0 then
|
||||||
|
begin
|
||||||
|
Writeln(stderr,'Error in heap memory list');
|
||||||
|
Writeln(stderr,'More memory blocks than expected');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if pp^.sig=$DEADBEEF then
|
||||||
|
begin
|
||||||
|
{ this one was not released !! }
|
||||||
|
call_stack(pp);
|
||||||
|
dec(i);
|
||||||
|
end
|
||||||
|
else if pp^.sig<>$AAAAAAAA then
|
||||||
|
dump_error(pp);
|
||||||
pp:=pp^.previous;
|
pp:=pp^.previous;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -201,7 +279,10 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.2 1998-10-02 10:35:38 peter
|
Revision 1.3 1998-10-06 17:09:13 pierre
|
||||||
|
+ added trace of first dispose for errors
|
||||||
|
|
||||||
|
Revision 1.2 1998/10/02 10:35:38 peter
|
||||||
+ quicktrace
|
+ quicktrace
|
||||||
|
|
||||||
Revision 1.1 1998/10/01 14:54:20 peter
|
Revision 1.1 1998/10/01 14:54:20 peter
|
||||||
|
Loading…
Reference in New Issue
Block a user