3 This file is part of the Free Pascal run time library
.
4 Copyright (c
) 1999-2000 by the Free Pascal development team
.
8 See the file COPYING
.FPC
, included
in this distribution
,
9 for details about the copyright
.
11 This program is distributed
in the hope that it will be useful
,
12 but WITHOUT ANY WARRANTY
; without even the implied warranty of
13 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE
.
15 **********************************************************************}
18 { 0.99.12 had a bug that initialization
/finalization only worked
for
29 { define EXTRA to add more
31 - keep all memory after release
and
32 check by CRC value
if not changed after release
33 WARNING this needs extremely much
memory (PM
) }
36 FillExtraInfoType
= procedure(p
: pointer
);
38 { allows to add several longint value that can help
40 see
for instance ppheap
.pas unit of the compiler source PM
}
42 Procedure
SetExtraInfo( size
: longint
;func
: FillExtraInfoType
);
43 Procedure
SetHeapTraceOutput(const name
: string
);
47 splitted
in two
if memory is released
!! }
53 quicktrace
: boolean
=true;
54 { calls
halt() on error by default
!! }
55 HaltOnError
: boolean
= true;
56 { set this to
true if you suspect that memory
57 is freed several times
}
59 keepreleased
: boolean
=true;
60 add_tail
: boolean
= true;
62 keepreleased
: boolean
=false;
63 add_tail
: boolean
= false;
66 this allows to test
for writing into that part
}
67 usecrc
: boolean
= true;
76 { allows to add custom info
in heap_mem_info
}
77 extra_info_size
: longint
= 0;
78 exact_info_size
: longint
= 0;
79 EntryMemUsed
: longint
= 0;
80 { function to fill this info up
}
81 fill_extra_info
: FillExtraInfoType
= nil;
82 error_in_heap
: boolean
= false;
83 inside_trace_getmem
: boolean
= false;
86 pheap_mem_info
= ^theap_mem_info
;
87 { warning the size of theap_mem_info
88 must be a multiple of
8
89 because otherwise you will get
90 problems
when releasing the usual memory part
!!
91 sizeof(theap_mem_info
= 16+tracesize
*4 so
92 tracesize must be even
!! PM
}
93 theap_mem_info
= record
95 next : pheap_mem_info
;
99 release_sig
: longint
;
100 prev_valid
: pheap_mem_info
;
102 calls
: array
[1..tracesize
] of longint
;
113 heap_valid_last
: pheap_mem_info
;
115 heap_mem_root
: pheap_mem_info
;
117 freemem_cnt
: longint
;
119 freemem_size
: longint
;
121 freemem8_size
: longint
;
124 {*****************************************************************************
126 *****************************************************************************}
130 Crc32Tbl
: array
[0..255] of longword
;
132 Crc32Tbl
: array
[0..255] of longint
;
135 procedure MakeCRC32Tbl
;
149 crc
:=(crc shr
1) xor
$edb88320
158 {$define Range_check_on
}
163 Function
UpdateCrc32(InitCrc
:longint;var InBuf
;InLen
:Longint):longint;
171 InitCrc
:=Crc32Tbl
[byte(InitCrc
) xor
byte(p^
)] xor (InitCrc shr
8);
174 UpdateCrc32
:=InitCrc
;
177 Function
calculate_sig(p
: pheap_mem_info
) : longint
;
183 crc
:=UpdateCrc32(crc
,p^
.size
,sizeof(longint
));
184 crc
:=UpdateCrc32(crc
,p^
.calls
,tracesize
*sizeof(longint
));
185 if extra_info_size
>0 then
186 crc
:=UpdateCrc32(crc
,p^
.extra_info
,exact_info_size
);
189 { Check also
4 bytes just after allocation
!! }
190 pl
:=pointer(p
)+extra_info_size
+sizeof(theap_mem_info
)+p^
.size
;
191 crc
:=UpdateCrc32(crc
,pl^
,sizeof(longint
));
197 Function
calculate_release_sig(p
: pheap_mem_info
) : longint
;
203 crc
:=UpdateCrc32(crc
,p^
.size
,sizeof(longint
));
204 crc
:=UpdateCrc32(crc
,p^
.calls
,tracesize
*sizeof(longint
));
205 if extra_info_size
>0 then
206 crc
:=UpdateCrc32(crc
,p^
.extra_info
,exact_info_size
);
207 { Check the whole of the whole allocation
}
208 pl
:=pointer(p
)+extra_info_size
+sizeof(theap_mem_info
);
209 crc
:=UpdateCrc32(crc
,pl^
,p^
.size
);
210 { Check also
4 bytes just after allocation
!! }
213 { Check also
4 bytes just after allocation
!! }
214 pl
:=pointer(p
)+extra_info_size
+sizeof(theap_mem_info
)+p^
.size
;
215 crc
:=UpdateCrc32(crc
,pl^
,sizeof(longint
));
217 calculate_release_sig
:=crc
;
221 {$ifdef Range_check_on
}
223 {$undef Range_check_on
}
224 {$endif Range_check_on
}
226 {*****************************************************************************
228 *****************************************************************************}
230 procedure
call_stack(pp
: pheap_mem_info
;var ptext
: text
);
234 writeln(ptext
,'Call trace for block 0x',hexstr(longint(pointer(pp
)+sizeof(theap_mem_info
)),8),' size ',pp^
.size
);
235 for i
:=1 to tracesize
do
236 if pp^
.calls
[i
]<>0 then
237 writeln(ptext
,BackTraceStrFunc(pp^
.calls
[i
]));
238 for i
:=0 to (exact_info_size div
4)-1 do
239 writeln(ptext
,'info ',i
,'=',plongint(pointer(@pp^
.extra_info
)+4*i
)^
);
242 procedure
call_free_stack(pp
: pheap_mem_info
;var ptext
: text
);
247 writeln(ptext
,'Call trace for block at 0x',hexstr(longint(pointer(pp
)+sizeof(theap_mem_info
)),8),' size ',pp^
.size
);
248 for i
:=1 to tracesize div
2 do
249 if pp^
.calls
[i
]<>0 then
250 writeln(ptext
,BackTraceStrFunc(pp^
.calls
[i
]));
251 writeln(ptext
,' was released at ');
252 for i
:=(tracesize div
2)+1 to tracesize
do
253 if pp^
.calls
[i
]<>0 then
254 writeln(ptext
,BackTraceStrFunc(pp^
.calls
[i
]));
255 for i
:=0 to (exact_info_size div
4)-1 do
256 writeln(ptext
,'info ',i
,'=',plongint(pointer(@pp^
.extra_info
)+4*i
)^
);
260 procedure
dump_already_free(p
: pheap_mem_info
;var ptext
: text
);
262 Writeln(ptext
,'Marked memory at 0x',HexStr(longint(pointer(p
)+sizeof(theap_mem_info
)),8),' released');
263 call_free_stack(p
,ptext
);
264 Writeln(ptext
,'freed again at');
265 dump_stack(ptext
,get_caller_frame(get_frame
));
268 procedure
dump_error(p
: pheap_mem_info
;var ptext
: text
);
270 Writeln(ptext
,'Marked memory at 0x',HexStr(longint(pointer(p
)+sizeof(theap_mem_info
)),8),' invalid');
271 Writeln(ptext
,'Wrong signature $',hexstr(p^
.sig
,8)
272 ,' instead of ',hexstr(calculate_sig(p
),8));
273 dump_stack(ptext
,get_caller_frame(get_frame
));
277 procedure
dump_change_after(p
: pheap_mem_info
;var ptext
: text
);
281 Writeln(ptext
,'Marked memory at 0x',HexStr(longint(pointer(p
)+sizeof(theap_mem_info
)),8),' invalid');
282 Writeln(ptext
,'Wrong release CRC $',hexstr(p^
.release_sig
,8)
283 ,' instead of ',hexstr(calculate_release_sig(p
),8));
284 Writeln(ptext
,'This memory was changed after call to freemem !');
285 call_free_stack(p
,ptext
);
286 pp
:=pointer(p
)+sizeof(theap_mem_info
)+extra_info_size
;
287 for i
:=0 to p^
.size-1
do
288 if byte(pp
[i
])<>$F0 then
289 Writeln(ptext
,'offset',i
,':$',hexstr(i
,8),'"',pp
[i
],'"');
293 procedure
dump_wrong_size(p
: pheap_mem_info
;size
: longint
;var ptext
: text
);
297 Writeln(ptext
,'Marked memory at 0x',HexStr(longint(pointer(p
)+sizeof(theap_mem_info
)),8),' invalid');
298 Writeln(ptext
,'Wrong size : ',p^
.size
,' allocated ',size
,' freed');
299 dump_stack(ptext
,get_caller_frame(get_frame
));
300 for i
:=0 to (exact_info_size div
4)-1 do
301 writeln(ptext
,'info ',i
,'=',plongint(@p^
.extra_info
+4*i
)^
);
306 function
is_in_getmem_list (p
: pheap_mem_info
) : boolean
;
311 is_in_getmem_list
:=false;
316 if ((pp^
.sig
<>$DEADBEEF) or usecrc
) and
317 ((pp^
.sig
<>calculate_sig(pp
)) or not usecrc
) and
318 (pp^
.sig
<> $AAAAAAAA) then
320 writeln(ptext^
,'error in linked list of heap_mem_info');
324 is_in_getmem_list
:=true;
327 if i
>getmem_cnt-freemem_cnt
then
328 writeln(ptext^
,'error in linked list of heap_mem_info');
333 {*****************************************************************************
335 *****************************************************************************}
337 Function
TraceGetMem(size
:longint):pointer;
343 inc(getmem_size
,size
);
344 inc(getmem8_size
,((size
+7) div
8)*8);
345 { Do the real GetMem
, but alloc also
for the info block
}
346 bp
:=size
+sizeof(theap_mem_info
)+extra_info_size
;
348 inc(bp
,sizeof(longint
));
350 { Create the info block
}
351 pheap_mem_info(p
)^
.sig
:=$DEADBEEF;
352 pheap_mem_info(p
)^
.size
:=size
;
355 pl
:=pointer(p
)+bp-sizeof
(longint
);
358 bp
:=get_caller_frame(get_frame
);
359 for i
:=1 to tracesize
do
361 pheap_mem_info(p
)^
.calls
[i
]:=get_caller_addr(bp
);
362 bp
:=get_caller_frame(bp
);
364 { insert
in the linked list
}
365 if heap_mem_root
<>nil then
366 heap_mem_root^
.next:=pheap_mem_info(p
);
367 pheap_mem_info(p
)^
.previous
:=heap_mem_root
;
368 pheap_mem_info(p
)^
.next:=nil;
370 pheap_mem_info(p
)^
.prev_valid
:=heap_valid_last
;
371 heap_valid_last
:=pheap_mem_info(p
);
372 if not assigned(heap_valid_first
) then
373 heap_valid_first
:=pheap_mem_info(p
);
376 { must be changed before fill_extra_info is called
377 because checkpointer can be called from within
380 if assigned(fill_extra_info
) then
382 inside_trace_getmem
:=true;
383 fill_extra_info(@pheap_mem_info(p
)^
.extra_info
);
384 inside_trace_getmem
:=false;
386 { update the pointer
}
388 pheap_mem_info(p
)^
.sig
:=calculate_sig(pheap_mem_info(p
));
389 inc(p
,sizeof(theap_mem_info
)+extra_info_size
);
394 {*****************************************************************************
396 *****************************************************************************}
398 function
TraceFreeMemSize(var p
:pointer;size
:longint):longint;
400 i
,bp
, ppsize
: longint
;
403 pp2
: pheap_mem_info
;
406 inc(freemem_size
,size
);
407 inc(freemem8_size
,((size
+7) div
8)*8);
408 ppsize
:= size
+ sizeof(theap_mem_info
)+extra_info_size
;
410 ppsize
:=ppsize
+sizeof(longint
);
411 dec(p
,sizeof(theap_mem_info
)+extra_info_size
);
412 pp
:=pheap_mem_info(p
);
413 if not quicktrace
and not(is_in_getmem_list(pp
)) then
415 if (pp^
.sig
=$AAAAAAAA) and not usecrc
then
418 dump_already_free(pp
,ptext^
);
419 if haltonerror
then halt(1);
421 else if ((pp^
.sig
<>$DEADBEEF) or usecrc
) and
422 ((pp^
.sig
<>calculate_sig(pp
)) or not usecrc
) then
425 dump_error(pp
,ptext^
);
427 dump_error(pp
,error_file
);
429 { don
't release anything in this case !! }
430 if haltonerror then halt(1);
433 else if pp^.size<>size then
436 dump_wrong_size(pp,size,ptext^);
438 dump_wrong_size(pp,size,error_file);
440 if haltonerror then halt(1);
441 { don't release anything
in this
case !! }
444 { now it is released
!! }
446 if not keepreleased
then
448 if pp^
.next<>nil then
449 pp^
.next^
.previous
:=pp^
.previous
;
450 if pp^
.previous
<>nil then
451 pp^
.previous^
.next:=pp^
.next;
452 if pp
=heap_mem_root
then
453 heap_mem_root
:=heap_mem_root^
.previous
;
457 bp
:=get_caller_frame(get_frame
);
458 for i
:=(tracesize div
2)+1 to tracesize
do
460 pp^
.calls
[i
]:=get_caller_addr(bp
);
461 bp
:=get_caller_frame(bp
);
465 { release the normal memory at least
!! }
466 { this way we keep all info about all released memory
!! }
470 dec(ppsize
,sizeof(theap_mem_info
)+extra_info_size
);
471 inc(p
,sizeof(theap_mem_info
)+extra_info_size
);
473 inc(p
,sizeof(theap_mem_info
)+extra_info_size
);
474 fillchar(p^
,size
,#240); { $F0 will lead to GFP if used as pointer ! }
475 { We want to check
if the memory was changed after release
!! }
476 pp^
.release_sig
:=calculate_release_sig(pp
);
477 if pp
=heap_valid_last
then
479 heap_valid_last
:=pp^
.prev_valid
;
480 if pp
=heap_valid_first
then
481 heap_valid_first
:=nil;
484 pp2
:=heap_valid_last
;
485 while assigned(pp2
) do
487 if pp2^
.prev_valid
=pp
then
489 pp2^
.prev_valid
:=pp^
.prev_valid
;
490 if pp
=heap_valid_first
then
491 heap_valid_first
:=pp2
;
495 pp2
:=pp2^
.prev_valid
;
500 i
:=SysFreeMemSize(p
,ppsize
);
501 dec(i
,sizeof(theap_mem_info
)+extra_info_size
);
503 dec(i
,sizeof(longint
));
508 function
TraceMemSize(p
:pointer):Longint;
512 l
:=SysMemSize(p-
(sizeof(theap_mem_info
)+extra_info_size
));
513 dec(l
,sizeof(theap_mem_info
)+extra_info_size
);
515 dec(l
,sizeof(longint
));
520 function
TraceFreeMem(var p
:pointer):longint;
525 pp
:=pheap_mem_info(pointer(p
)-(sizeof(theap_mem_info
)+extra_info_size
));
526 size
:=TraceMemSize(p
);
527 { this can never happend normaly
}
528 if pp^
.size
>size
then
530 dump_wrong_size(pp
,size
,ptext^
);
532 dump_wrong_size(pp
,size
,error_file
);
535 TraceFreeMem
:=TraceFreeMemSize(p
,pp^
.size
);
539 {*****************************************************************************
541 *****************************************************************************}
543 function
TraceReAllocMem(var p
:pointer;size
:longint):Pointer;
559 { Allocate a new block
? }
562 p
:=TraceGetMem(size
);
567 dec(p
,sizeof(theap_mem_info
)+extra_info_size
);
568 pp
:=pheap_mem_info(p
);
570 if ((pp^
.sig
<>$DEADBEEF) or usecrc
) and
571 ((pp^
.sig
<>calculate_sig(pp
)) or not usecrc
) then
574 dump_error(pp
,ptext^
);
576 dump_error(pp
,error_file
);
578 { don
't release anything in this case !! }
579 if haltonerror then halt(1);
582 { Do the real ReAllocMem, but alloc also for the info block }
583 bp:=size+sizeof(theap_mem_info)+extra_info_size;
585 inc(bp,sizeof(longint));
586 { the internal ReAllocMem is not allowed to move any data }
587 if not SysTryResizeMem(p,bp) then
590 inc(p,sizeof(theap_mem_info)+extra_info_size);
592 oldsize:=TraceMemSize(p);
593 newP := TraceGetMem(size);
596 move(p^,newP^,oldsize);
600 traceReAllocMem := p;
603 pp:=pheap_mem_info(p);
604 { adjust like a freemem and then a getmem, so you get correct
605 results in the summary display }
606 inc(freemem_size,pp^.size);
607 inc(freemem8_size,((pp^.size+7) div 8)*8);
608 inc(getmem_size,size);
609 inc(getmem8_size,((size+7) div 8)*8);
610 { Create the info block }
615 pl:=pointer(p)+bp-sizeof(longint);
618 bp:=get_caller_frame(get_frame);
619 for i:=1 to tracesize do
621 pp^.calls[i]:=get_caller_addr(bp);
622 bp:=get_caller_frame(bp);
624 if assigned(fill_extra_info) then
625 fill_extra_info(@pp^.extra_info);
626 { update the pointer }
628 pp^.sig:=calculate_sig(pp);
629 inc(p,sizeof(theap_mem_info)+extra_info_size);
635 {*****************************************************************************
637 *****************************************************************************}
645 __stklen : cardinal;external name '__stklen
';
646 __stkbottom : cardinal;external name '__stkbottom
';
647 edata : cardinal; external name 'edata
';
648 heap_at_init : pointer;
653 StartUpHeapEnd : pointer;
654 { I found no symbol for start of text section :(
655 so we usee the _mainCRTStartup which should be
656 in wprt0.ow or wdllprt0.ow PM }
657 text_begin : cardinal;external name '_mainCRTStartup
';
658 data_end : cardinal;external name '__data_end__
';
661 procedure CheckPointer(p : pointer);[public, alias : 'FPC_CHECKPOINTER
'];
665 get_ebp,stack_top : cardinal;
679 if cardinal(p)<$1000 then
686 stack_top:=__stkbottom+__stklen;
687 { allow all between start of code and end of data }
688 if cardinal(p)<=data_end then
691 if cardinal(p)<=cardinal(heap_at_init) then
693 { stack can be above heap !! }
695 if (cardinal(p)>=get_ebp) and (cardinal(p)<=stack_top) then
699 { I don't know where the stack is
in other OS
!! }
701 if (cardinal(p
)>=$40000) and (p
<=HeapOrg
) then
707 if (cardinal(p
)>get_ebp
) and
708 (cardinal(p
)<Win32StackTop
) then
714 { first try valid list faster
}
720 { inside this valid block
! }
721 { we can be changing the extrainfo
!! }
722 if (cardinal(p
)>=cardinal(pp
)+sizeof(theap_mem_info
){+extra_info_size
}) and
723 (cardinal(p
)<=cardinal(pp
)+sizeof(theap_mem_info
)+extra_info_size
+pp^
.size
) then
725 { check allocated block
}
726 if ((pp^
.sig
=$DEADBEEF) and not usecrc
) or
727 ((pp^
.sig
=calculate_sig(pp
)) and usecrc
) or
728 { special
case of the fill_extra_info call
}
729 ((pp
=heap_valid_last
) and usecrc
and (pp^
.sig
=$DEADBEEF)
730 and inside_trace_getmem
) then
734 writeln(ptext^
,'corrupted heap_mem_info');
735 dump_error(pp
,ptext^
);
742 if i
>getmem_cnt-freemem_cnt
then
744 writeln(ptext^
,'error in linked list of heap_mem_info');
753 { inside this block
! }
754 if (cardinal(p
)>=cardinal(pp
)+sizeof(theap_mem_info
)+cardinal(extra_info_size
)) and
755 (cardinal(p
)<=cardinal(pp
)+sizeof(theap_mem_info
)+cardinal(extra_info_size
)+cardinal(pp^
.size
)) then
757 if ((pp^
.sig
=$DEADBEEF) and not usecrc
) or
758 ((pp^
.sig
=calculate_sig(pp
)) and usecrc
) then
762 writeln(ptext^
,'pointer $',hexstr(longint(p
),8),' points into invalid memory block');
763 dump_error(pp
,ptext^
);
770 writeln(ptext^
,'error in linked list of heap_mem_info');
774 writeln(ptext^
,'pointer $',hexstr(longint(p
),8),' does not point to valid memory block');
782 {*****************************************************************************
784 *****************************************************************************}
790 ExpectedMemAvail
: longint
;
793 Writeln(ptext^
,'Heap dump by heaptrc unit');
794 Writeln(ptext^
,getmem_cnt
, ' memory blocks allocated : ',getmem_size
,'/',getmem8_size
);
795 Writeln(ptext^
,freemem_cnt
,' memory blocks freed : ',freemem_size
,'/',freemem8_size
);
796 Writeln(ptext^
,getmem_cnt-freemem_cnt
,' unfreed memory blocks : ',getmem_size-freemem_size
);
797 Write(ptext^
,'True heap size : ',system
.HeapSize
);
798 if EntryMemUsed
> 0 then
799 Writeln(ptext^
,' (',EntryMemUsed
,' used in System startup)')
802 Writeln(ptext^
,'True free heap : ',MemAvail
);
803 ExpectedMemAvail
:=system
.HeapSize-
(getmem8_size-freemem8_size
)-
804 (getmem_cnt-freemem_cnt
)*(sizeof(theap_mem_info
)+extra_info_size
)-EntryMemUsed
;
805 If ExpectedMemAvail
<>MemAvail
then
806 Writeln(ptext^
,'Should be : ',ExpectedMemAvail
);
807 i
:=getmem_cnt-freemem_cnt
;
812 Writeln(ptext^
,'Error in heap memory list');
813 Writeln(ptext^
,'More memory blocks than expected');
816 if ((pp^
.sig
=$DEADBEEF) and not usecrc
) or
817 ((pp^
.sig
=calculate_sig(pp
)) and usecrc
) then
819 { this one was
not released
!! }
820 if exitcode
<>203 then
821 call_stack(pp
,ptext^
);
824 else if pp^
.sig
<>$AAAAAAAA then
826 dump_error(pp
,ptext^
);
828 dump_error(pp
,error_file
);
833 else if pp^
.release_sig
<>calculate_release_sig(pp
) then
835 dump_change_after(pp
,ptext^
);
836 dump_change_after(pp
,error_file
);
859 {*****************************************************************************
861 *****************************************************************************}
863 function
TraceAllocMem(size
:longint):Pointer;
865 TraceAllocMem
:=SysAllocMem(size
);
869 {*****************************************************************************
870 No specific tracing calls
871 *****************************************************************************}
873 function TraceMemAvail
:longint;
875 TraceMemAvail
:=SysMemAvail
;
878 function TraceMaxAvail
:longint;
880 TraceMaxAvail
:=SysMaxAvail
;
883 function TraceHeapSize
:longint;
885 TraceHeapSize
:=SysHeapSize
;
889 {*****************************************************************************
890 Install MemoryManager
891 *****************************************************************************}
894 TraceManager
:TMemoryManager=(
895 Getmem
: TraceGetMem
;
896 Freemem
: TraceFreeMem
;
897 FreememSize
: TraceFreeMemSize
;
898 AllocMem
: TraceAllocMem
;
899 ReAllocMem
: TraceReAllocMem
;
900 MemSize
: TraceMemSize
;
901 MemAvail
: TraceMemAvail
;
902 MaxAvail
: TraceMaxAvail
;
903 HeapSize
: TraceHeapsize
;
909 because this gives long long listings
}
910 { clear inoutres
, in case the program that quit didn
't }
912 if (exitcode<>0) and (erroraddr<>nil) then
914 Writeln(ptext^,'No heap dump by heaptrc unit
');
915 Writeln(ptext^,'Exitcode
= ',exitcode);
916 if ptext<>@stderr then
923 if not error_in_heap then
925 if error_in_heap and (exitcode=0) then
930 if ptext<>@stderr then
937 Procedure SetHeapTraceOutput(const name : string);
940 if ptext<>@stderr then
945 assign(ownfile,name);
952 for i:=0 to Paramcount do
953 write(ptext^,paramstr(i),' ');
957 procedure SetExtraInfo( size : longint;func : fillextrainfotype);
962 writeln(ptext^,'Setting extra info is only possible at start
!! ');
967 { the total size must stay multiple of 8 !! }
968 exact_info_size:=size;
969 extra_info_size:=((size+7) div 8)*8;
970 fill_extra_info:=func;
975 EntryMemUsed:=System.HeapSize-MemAvail;
977 SetMemoryManager(TraceManager);
980 Assign(error_file,'heap
.err
');
983 { checkpointer init }
985 Heap_at_init:=HeapPtr;
988 StartupHeapEnd:=HeapEnd;
995 Revision 1.1 2002/02/19 08:25:23 sasu
998 Revision 1.1.2.2 2000/12/15 13:02:30 jonas
999 * added some typecasts so some expressiosn aren't evaluated anymore
in
1000 64bit
when rangechecking is on
1002 Revision
1.1.2.1 2000/08/24 08:59:35 jonas
1003 * clear inoutres
in traceexit before writing
anything (to avoid an RTE
1004 when writing the heaptrc output
when a program didn
't handle ioresult)
1006 Revision 1.1 2000/07/13 06:30:47 michael
1009 Revision 1.43 2000/05/18 17:03:27 peter
1010 * fixed reallocmem with double removing from heap_mem_root list
1011 * fixed reallocmem getmem/freemem count, now both are increased and
1012 the _size8 counts are also increased
1014 Revision 1.42 2000/04/27 15:35:50 pierre
1015 * fix for bug report 929
1017 Revision 1.41 2000/02/10 13:59:35 peter
1018 * fixed bug with reallocmem to use the wrong size when copying the
1019 data to the new allocated pointer
1021 Revision 1.40 2000/02/09 16:59:30 peter
1024 Revision 1.39 2000/02/07 10:42:44 peter
1025 * use backtracestrfunc()
1027 Revision 1.38 2000/02/02 11:13:15 peter
1028 * fixed tracereallocmem which supplied the wrong size for tryresize
1030 Revision 1.37 2000/01/31 23:41:30 peter
1031 * reallocmem fixed for freemem() call when size=0
1033 Revision 1.36 2000/01/20 14:25:51 jonas
1034 * finally fixed tracereallocmem completely
1036 Revision 1.35 2000/01/20 13:17:11 jonas
1037 * another problme with realloc fixed (one left)
1039 Revision 1.34 2000/01/20 12:35:35 jonas
1040 * fixed problem with reallocmem and heaptrc
1042 Revision 1.33 2000/01/07 16:41:34 daniel
1045 Revision 1.32 2000/01/07 16:32:24 daniel
1046 * copyright 2000 added
1048 Revision 1.31 2000/01/05 13:56:55 jonas
1049 * fixed traceReallocMem with nil pointer (simply calls traceGetMem now in
1052 Revision 1.30 2000/01/03 19:37:52 peter
1053 * fixed reallocmem with p=nil
1055 Revision 1.29 1999/11/14 21:35:04 peter
1058 Revision 1.28 1999/11/09 22:32:23 pierre
1059 * several extra_size_info fixes
1061 Revision 1.27 1999/11/06 14:35:38 peter
1064 Revision 1.26 1999/11/01 13:56:50 peter
1065 * freemem,reallocmem now get var argument
1067 Revision 1.25 1999/10/30 17:39:05 peter
1068 * memorymanager expanded with allocmem/reallocmem
1070 Revision 1.24 1999/09/17 17:14:12 peter
1071 + new heap manager supporting delphi freemem(pointer)
1073 Revision 1.23 1999/09/10 17:13:41 peter
1076 Revision 1.22 1999/09/08 16:14:41 peter
1079 Revision 1.21 1999/08/18 12:03:16 peter
1080 * objfpc mode for 0.99.12
1082 Revision 1.20 1999/08/17 14:56:03 michael
1083 Removed the mode for objpas