IonicWind Software

IWBasic => The Roundtable => Topic started by: Parker on March 16, 2007, 11:12:10 PM

Title: Counting unfreed memory EB version
Post by: Parker on March 16, 2007, 11:12:10 PM
This is the Emergence version of the code posted in the Aurora forums about counting the memory you've forgotten to delete. Refer to that topic for more information (link (http://www.ionicwind.com/forums/index.php/topic,1557.0.html)).

The main differences are that _dont_store_memory isn't needed because of the way linked lists are created, and you don't need to (and shouldn't) call free_global_list() because it is done automatically for you with ONEXIT.

declare import,GlobalAlloc(flags as uint,size as int),uint
declare import,GlobalFree(p as uint),uint

$define _ALLOC_TAG 0x19F30AD7

pointer alloclist
int _dont_store_memory

type _alloc_info
uint tag
pointer address
uint size
pointer listnode
end type

'' The following methods aren't meant for general use.

_asm
%define __NEW _mynew
%define __DELETE _mydelete
_endasm

global sub get_type_size( typ:int ),int
select typ
case @TYPESTRING
return 255
case @TYPEWSTRING
return 512
case @TYPECHAR
case& @TYPEUSER
return 1
case @TYPEWORD
return 2
case @TYPEDOUBLE
case& @TYPEINT64
return 8
end select
''default
return 4
end sub

global sub free_global_list( dt:pointer )
if alloclist <> 0 then
GlobalFree( alloclist )
alloclist = 0
end if
end sub

global sub add_global_pointer( info:pointer )
if alloclist = 0 then
alloclist = ListCreate( )
onexit( &free_global_list, 0 )
end if

ListAddHead( alloclist, info )
*<_alloc_info>info.listnode = ListGetFirst( alloclist )
end sub

global sub remove_global_pointer( node:pointer )
if alloclist = 0 then return

ListRemove( node )
end sub

global sub _mynew( typ:int, size:int ),uint
pointer info
settype info, _alloc_info

size *= get_type_size( typ & 0xFF )
if _dont_store_memory = 0 then _
size += len( _alloc_info )

info = GlobalAlloc( 0x40, size )
if _dont_store_memory <> 0 then _
return info

*info.tag = _ALLOC_TAG

*info.size = size - len( _alloc_info )
*info.address = info + len( _alloc_info )

add_global_pointer( info )

return *info.address
end sub

global sub _mydelete( p:pointer )
if p < len( _alloc_info ) then _
return

p -= len( _alloc_info )

if *<_alloc_info>p.tag <> _ALLOC_TAG then
print "Delete error - invalid pointer"
return
end if

remove_global_pointer( *<_alloc_info>p.listnode )
GlobalFree( p )
end sub

'' Feel free to use these methods.
global sub FreeLostMemory( )
pointer info : info = 0
settype info, _alloc_info
pointer n, temp

if alloclist = 0 then _
return

n = ListGetFirst( alloclist )
while n <> 0
info = ListGetData( n )
GlobalFree( info )
temp = n
n = ListGetNext( n )
ListRemove( temp )
wend
end sub

global sub DumpUnfreedMemory( )
pointer info : info = 0
int count : count = 0

if alloclist = 0 then
print "No memory recorded."
return
end if

print "\n--- Listing undeleted memory ---\n"
for info = each alloclist as _alloc_info
print "Address: 0x", hex$( *info.address ), "; Size (bytes): ", *info.size
count++
next
print "--- Found ", count, " unfreed memory addresses ---"
end sub

'' Test

type Type12Bytes
int x, y, z
end type

'' main
pointer x, y, t12
settype x, int
settype y, char
settype t12, Type12Bytes

x = new( int, 1 )
y = new( char, 1 )
t12 = new( Type12Bytes, 1 )

DumpUnfreedMemory( )

delete x
delete t12

DumpUnfreedMemory( )

FreeLostMemory( )

DumpUnfreedMemory( )

print "Done."
do:until inkey$<>""