All images not accounted for...

BlitzPlus Forums/BlitzPlus Programming/All images not accounted for...

WoeIsMe(Posted 2003) [#1]
Help! In my game, I have a routine that deletes all images one by one:
If image<>0 then FreeImage image : image=0

The problem is that I don't seem to have deleted all of the images, and I still have some seemingly left anaccounted for taking up video memory. How am I supposed to find all of these? Any ideas?


semar(Posted 2003) [#2]
Do you use copyimage in somewhere ?


WoeIsMe(Posted 2003) [#3]
No. I do load one particular image 4 separate times under different handles in the same loading routine:
scytheul2=LoadImage("Graphics\Scythe2\scythe ul.png")
MidHandle scytheul2
MaskImage scytheul2,255,0,255
scythedl2=LoadImage("Graphics\Scythe2\scythe ul.png")
MidHandle scythedl2
MaskImage scythedl2,255,0,255
RotateImage scythedl2,270
scythedr2=LoadImage("Graphics\Scythe2\scythe ul.png")
MidHandle scythedr2
MaskImage scythedr2,255,0,255
RotateImage scythedr2,180
scytheur2=LoadImage("Graphics\Scythe2\scythe ul.png")
MidHandle scytheur2
MaskImage scytheur2,255,0,255
RotateImage scytheur2,90
and later...
If scythedl2<>0 Then FreeImage scythedl2 : scythedl2=0
If scytheul2<>0 Then FreeImage scytheul2 : scytheul2=0
If scytheur2<>0 Then FreeImage scytheur2 : scytheur2=0
If scythedr2<>0 Then FreeImage scythedr2 : scythedr2=0

Could it be something to do with this? I'm a bit sceptical, 'cos I seem to be losing a lot more vidmem thatn these would account for. Any further ideas?


WoeIsMe(Posted 2003) [#4]
Anyone got any other ideas? This is a nasty problem for the game, so if anyone else could help, this would be greatly appreciated.


Andy_A(Posted 2003) [#5]
Just a thought. You wouldn't by chance be adding or deleting image handle variables from a function, would you? If so you need to declare the image handle variable name as global.

If that's not it, I don't know.

Cheers,

Andy


soja(Posted 2003) [#6]
Are we absolutely positive that FreeImage immediately de-allocates the memory internally?

(It's conceivable that Blitz might not deallocate the memory until it absolutely has to, for optimization purposes, but truthfully, I don't know.)


WoeIsMe(Posted 2003) [#7]
>Andy A

No, I don't use a function. I ran a little tes program to see what happens to images when you delete them, and I think it's pretty conclusive that there's images floating about in my game undeleted. The routine's as follows:
Graphics 800,600

firstvidmem=AvailVidMem()

timer=CreateTimer(15)

While Not KeyDown(1)
Color 255,255,0
WaitTimer timer

image1=LoadImage("image.png")
If KeyDown(28)=1 Then FreeImage image1 : image1=0

images=images+1

Print images
vidmem=AvailVidMem()
Print vidmem

Wend 
End

If you hold down enter, you see that the memory stays the same, because it is loaded and then deleted. Therefore, it means that I have images floating around that I haven't found.

I've tried setting the handles for the graphics as all global and seeing if they come up in the debug sidebar in the IDE, but all the images come up as 0. I can't find a single one that doesn't come up as 0 - even the ones that I've loaded and not deleted! This could be a solution, but I don't know what I'm doing wrong. Thanks so far. Any more ideas?


WendellM(Posted 2003) [#8]
That's puzzling. I thought that it might possibly have something to do with freeing the images in a different order than they were created. However, modifying your test routine to load four images then delete them in a different order deallocated memory as it should. I also tried putting in the MaskImage and RotateImage commands for each in case they were to blame, but deallocation worked as it should have again.

You don't do this in the test routine, but in your actual program, you aren't by chance comparing available video memory before setting the graphics mode with afterwards, are you?
firstvidmem=AvailVidMem()
Graphics 800,600
vidmem=AvailVidMem()
Print firstvidmem+", "+vidmem
WaitKey
End

That results in a "loss" of memory due to setting up buffers. Just grasping at straws... :)

all the images come up as 0. I can't find a single one that doesn't come up as 0 - even the ones that I've loaded and not deleted!


Hmm, that doesn't sound quite right. You might try adding DebugLog statements every time you delete an image, just to make sure that FreeImage is really being called. For example:
If scythedl2<>0 Then
 FreeImage scythedl2 : scythedl2=0
 DebugLog "Freed scythedl2"
else
 DebugLog "scythedl2 not freed"
endif

To save lots of typing, this could be done in a function. Oh, and maybe having a Global count of total images currently loaded (similar to your test program) and decrementing it when an image is freed could be helpful (in case you're already using DebugLog for other things and it'd be hard to read through all the text).


WoeIsMe(Posted 2003) [#9]
I don't check the beginning vidmem before the graphics mode is set. As a function, how would I be able to state the image handle in the function? This one's had me puzzled...

>Edit - I think I've managed it - just was expecting it to try to free an image called "handle" if I used this, rather than "image1".
If KeyDown(28)=1 Then imagefree(image1)
calls up...
Function imagefree(handle)
FreeImage handle : handle=0
End Function

Thanks. This should help me a lot!


WoeIsMe(Posted 2003) [#10]
AAAARGH! Well, at least I'm closer to finding the solution, but this is getting annoying! Here's my image-freeing function:
Function delete_image(handle)

Local handlenum

If  handle<>0 Then 
	FreeImage handle
	handlenum=handle
	handle=0 
	loadedimages=loadedimages-1
	DebugLog "Freed "+handlenum+" to "+handle
Else 
	DebugLog handle+" not freed" 
EndIf 

End Function

This means I can check to see if an image has been deleted... or not. The problem is that the images that I have loaded go through the routine and come out in debug as (for example):
Freed 28574048 to 0
Freed 28573792 to 0
Freed 28606112 to 0
Freed 28574288 to 0
Which is all well and good, but then I do the deleting routine again, and though these images should be deleted, it comes out as:
Freed 28574048 to 0
Freed 28573792 to 0
Freed 28606112 to 0
Freed 28574288 to 0
which quite obviously shows that they haven't been deleted. This is probably the source of the memory problems, but as for the solution, I have no idea what to do! Please help!!!


WendellM(Posted 2003) [#11]
;Blitz normally passes variables by value, with no way to pass by reference
;(short of using Globals, which negates the point of explicitly passsing them)

a=100
b=10
Print "pre: "+a   ; displays 100
Print "pre: "+b   ; displays 10
foo(a,b)
Print "post: "+ a ; displays 100
Print "post: "+b  ; displays 10
Print"---"

;However, Types are always passed by reference

Type bartype
 Field a
 Field b
End Type

bar.bartype=New bartype

bar\a=100
bar\b=10
Print "pre: "+bar\a   ; displays 100
Print "pre: "+bar\b   ; displays 10
foobar(bar)
Print "post: "+ bar\a ; displays 200
Print "post: "+bar\b  ; displays 11

WaitKey
End


Function foo(a,b)
 a=200 ; these changes will not matter outside this function
 b=b+1
End Function

Function foobar(baz.bartype)
 baz\a=200 ; these changes *will* matter outside this function
 baz\b=baz\b+1
End Function

This shows how the variables passed to foo() are not affected outside of foo() since only the *values* of a & b are passed to it, not "the real" a & b.

I would have expected your function to cause a problem when it tried to FreeImage a handle that had already been freed, but that doesn't happen:
Graphics 800,600
FreeImage 12345 ; just a number picked out of thin air
FreeImage 12345 ; even worse, we're freeing this nonexistent handle twice!
hdl=CreateImage(32,32)
FreeImage hdl
FreeImage hdl ; Blitz has no problem with this

Print "No boom. Press a key."
WaitKey 
End


(BTW, there's a similar discussion about "missing memory" for 3D at http://blitzbasic.com/bbs/posts.php?topic=25942 )


Drgnhrt(Posted 2003) [#12]
Maybe this works.


global Picture1=loadimage("PICTURE.bmp")
maskimage 255,0,255

picture2=picture1
picture3=picture1
picture4=picture1

when you don't need the picture anymore
picture2=0
picture3=0
picture4=0

to free the image from memory
if picture2=0 and picture3=0 and picture4=0 then
freeimage picture1
end if

this way the picture loads once instead of four times.

later


WoeIsMe(Posted 2003) [#13]
Well, I seem to have solved that delelting-images-that-aren't-there problem. I just added:
imagefree(image) : image=0
and everything seems to be fine. I've also added a bit of code to tell me how much memory is freed when I delete an image, which is of great use. Still, the problem remains as to where the faults are, so keep those solutions coming! Thanks so far!

>EDIT
YESSSS! Problem solved! It turns out I wasn't freeing the fonts correctly, so it kept on loading the fonts again and again - not the images! I can't believe that after all that, the problem was THAT! Thanks to all of you - your advice is incredibly valuable, and without it, I probably wouldn't have worked it out anyway. And you've all solved me a hell of a load of problems I'm likely to have encountered in the future. Thanks to you all!


MSW(Posted 2003) [#14]
Sorry to pull this old thread back up...but thought it might prove helpful :P



This:

Function delete_image(handle)

Local handlenum

If  handle<>0 Then 
	FreeImage handle
	handlenum=handle
	handle=0 
	loadedimages=loadedimages-1
	DebugLog "Freed "+handlenum+" to "+handle
Else 
	DebugLog handle+" not freed" 
EndIf 

End Function



Should be:
Function delete_image(handle)

Local handlenum

If  handle<>0 Then 
	FreeImage handle
	handlenum=handle
	handle=0 
	loadedimages=loadedimages-1
	DebugLog "Freed "+handlenum+" to "+handle
Else 
	DebugLog handle+" not freed" 
EndIf 

Return handle ;<----------right here...a Function is designed to return a value
End Function



Then when you call the function you do this:

handle = delete_image(handle)


NOT this:

delete_image(handle) : handle = 0



WoeIsMe(Posted 2003) [#15]
Thanks! The problem's solved, but thanks for the advice. I'm sure it could save me some typing time. :)