Image not freed?
BlitzMax Forums/BlitzMax Beginners Area/Image not freed?
| ||
I'm busy learning BlitzMax (Mark, damn, it rules!) and I was wondering where all the commands like FreeImage are gone. I guess "release" does the same? If so, why is the handle to the image released, and not the actual memory it uses? Please try the example below. (I have blitzMax on M:\ so you have to change it in C:\ or something else) Strict Graphics 800,600,0 Type Oink Field x% Field y% Field image Function Create:Oink(a$) ' The constructor refers to object Oink (After the ':") and asks for a string as argument. ' A function does not know anything about where it is, unlike the method, so we must do this. Print "At start, mem: "+MemAlloced() Local o:Oink = New Oink Local x, y, image o.x = x o.y = y o.x = 100 o.y = 200 o.image = image o.image = LoadImage ("M:\Blitzmax\samples\birdie\games\platformgame\media\tiles\block1.PNG") Print "Object created, image loaded, mem: "+MemAlloced() Return o End Function Method Destroy () ' Be gone, thou evil object! Release image FlushMem Print "Object removed, mem: "+MemAlloced() End Method End Type ' --------------------------------------------------------------------------------------------- Local o:Oink = Oink.Create("HAHA!") o.Destroy() End Note to Mark: a lot of commands can use some additional descriptions. In Blitz you used to 1. explain what it does (like now), 2. give a more human description of what it does "chit-chat", and 3. an example. Well, I miss (2) for some commands :-) |
| ||
At start, mem: 84241 Object created, image loaded, mem: 7241544 Object removed, mem: 7241712 |
| ||
Euh, thanks Perturbatio. I wasn't clear enough with my question: Why is the memory not back at 84241, or close to that value? |
| ||
at a guess, it's because you are testing the free mem before the type has been instantiated as well, but when you show mem after the image is removed, the type itself still exists. |
| ||
Hmmm okay, I wanted to delete the object From the method Destroy, but ofcourse that is not possible. I would need a function (I don't know if that is possible as well, I guess so). Correct code, which ends up with even less (?) memory than at start: Strict Graphics 800,600,0 ' methods werken alleen met bestaande objecten ' je kan Method New gebruiken om object met b:blah = new blah() aan te maken, ' maar een constructor is uitgebreider, omdat je argumenten kunt gebruiken. ' je maakt dan een object aan met o:blah = blah.MaakAan("BLAH") Type Oink Field x% Field y% Field image Function Create:Oink(a$) ' The constructor refers to object Oink (After the ':") and asks for a string as argument. ' A function does not know anything about where it is, unlike the method, so we must do this. Local o:Oink = New Oink Local x, y, image o.x = x o.y = y o.x = 100 o.y = 200 o.image = image o.image = LoadImage ("M:\Blitzmax\samples\birdie\games\platformgame\media\tiles\block1.PNG") Return o End Function Method DestroyMedia () ' Be gone, thou evil object! Release image End Method End Type ' --------------------------------------------------------------------------------------------- Print "At start, mem: "+MemAlloced() Local o:Oink = Oink.Create("HAHA!") o.DestroyMedia() Release o FlushMem Print "Object removed, mem: "+MemAlloced() End |
| ||
yeah, I just did a test similar to that and got the same results. It's a little perplexing. What does concern me is that when you do MemAlloced() at the start, I get 84241, once the image is loaded, it returns 7241651 which is two digits longer than before. |
| ||
not a solution to the memory issues, but a Destroy function: |
| ||
Perhaps Blitzmax uses some memory to build up some stuff, to initialize stuff that can be removed safely with FlushMem? Dunno, just an idea :) Now, I want to be able to free my object with the "constructor" principle (I'd better call it "destructor" then). How can I remove the image and the object itself using a function inside an object? Thanks, Jeroen |
| ||
^ /|\ | | |
| ||
Heh, heh I didn't see that codebox before! Thank you. |
| ||
I'm busy learning BlitzMax (Mark, damn, it rules!) and I was wondering where all the commands like FreeImage are gone. They are pointless now. I guess "release" does the same? No. Release is a command that specifies that you're done with an integer reference to an object. FlushMem is the command that actually frees up memory. Witness:So the answer to the question "How do you free images in BlitzMAX?" is "You don't, BlitzMAX and it's pseudo garbage collector does it for you!". |
| ||
Hmmmmm, I'm very B3D oriented, so some things are confusing to me. I have some questions on your code snippet, FlameDuck:Field image:TImage What is TImage exactly, why not just 'image'? And secondly, does the garbage collector only work when I use A "Tlist"? |
| ||
Hi, 'TImage' is a Type - its returned by LoadImage and used by DrawImage etc. Basically, this means there are 2 ways to refer to images. The classic way... Local image=LoadImage( "Blah" ) 'nice 'n' friendly... ...and the 'new' way... Local image:TImage=LoadImage( "Blah" ) 'bit more verbose... If you use the classic way, you must later release the image using 'Release'... Release image ...and you can think of Release as the equivalent of FreeImage, FreeSound, FreeWhatever. If you use the new way, it's (almost) all handled for you: the image will be deleted the next time 'FlushMem' is called and it's no longer in use. And all this has nothing to do with lists! |
| ||
Thanks! ....But, still not entirely clear to me. I understand the "classic way". Release is the equivalent of all "free" commands. Handy. But, the "new way" seems unclear to me; how does the garbage collector know something is used or not? In your example, you make a "Blah" image, and then later on you say "flushMem". But, if I don't delete anything manually, how can the garbage collector know what is obsolete or not? As you say, "the image will be deleted the next time 'FlushMem' is called". But why does it do that? I never told Blitz that the object is obsolete. Is the garbage collector looking at which objects are in a Tlist and not? Hmmm, I hope you understand what I'm trying to tell :) |
| ||
But, the "new way" seems unclear to me; how does the garbage collector know something is used or not? Because it counts how many types you've made. Once you don't have anything left that references the data in question (and thus no way to access it) the garbage collector releases it's resources. But, if I don't delete anything manually, how can the garbage collector know what is obsolete or not? It can't know when you're done using it (what I assume you mean when you say obsolete). But what it can tell is when you couldn't possibly use it anymore, even if you wanted to, at least as long as you're using types, and not the "classic way". As you say, "the image will be deleted the next time 'FlushMem' is called". But why does it do that? I never told Blitz that the object is obsolete. You don't have to. It counts how many objects you have in play, and when that count reaches zero, it goes "poof". What is TImage exactly, why not just 'image'? Because BlitzMAXs types all (?) use "Hungarian Notation". Now hungarian notation is a discipline where by you prefix (typically) a letter to the actual variable name or reference. For instance a float that stores the X position of something could be called fXPosition. In Blitz3D the hungarian notation for this would be XPosition# (if you used it religiously).Hungarian Notation is a mnemonic technique used to indentify what kind of references you're currently working with, and provides a way to distinguish myPlayer - the object, from myPlayer - the number. And secondly, does the garbage collector only work when I use A "Tlist"? No. The TList is just collector type (note the leading T), that makes juggling objects around much easier. They function similarilly to the way Types used to work in the "Classic way", except now you can have more of them for each type (you could have a list of aliens for each level, and so on, allowing much more advanced object hierarchies than what was possible using Blitz3D), the downside being you have to add them all manually. |
| ||
Thanks Mikkel. Please tell if I'm right with my conclusion, based on Mark's and Mikkel's answers: ------------------------------------------------------ OLD WAY: When I load a JPG or whatever media like this: Local image=LoadImage( "Blah.jpg" ) ... The *object* TIimage is *not* returned, just a reference to the image. This is why you will need to release the image manually and the garbage collector doesn't know anything 'bout it. ------------------------------------------------------ NEW WAY: In order to do this, I will need to load stuff like this: Local image:TImage=LoadImage( "Blah.jpg" ) ...Where TIimage is the type/object that LoadImage returns. This is how the garbage collector can keep track of it's existance as an object. When I 'release object', I release the reference. When FlushMem is reached, Blitz sees there is no reference to the image anymore, and deletes everything in the object: variables, references to media like textures...everything what may exist in the object, or type. |
| ||
Sounds about right to me... |
| ||
Pretty much. The only gotcha I've come across is when working with streams, which still have to be closed manually. |
| ||
.. The *object* TIimage is *not* returned, just a reference to the image. This is why you will need to release the image manually and the garbage collector doesn't know anything 'bout it. Not exactly. A reference to the object TImage is returned. That TImage's internal count is incremented because it realises there is an integer reference to it lose in the system and to reduce that count in order for that TImage to be destroyed you must call Release so it can reduce the count. |