News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

CreateSolidBrush

Started by xroot, June 19, 2011, 03:38:39 PM

Previous topic - Next topic

xroot

I have a loop with these two lines and it works.
I was told that I would run out of brushes doing it this way.
Is this wrong to do it this way?? :tdown :thumbu
Thanks

   invoke nrandom,0ffffffh
   invoke SelectObject,hDC,rv(CreateSolidBrush,eax)  :naughty:


dedndave

if you look at the docs for SelectObject, you will find that it returns the handle for the object that is being replaced
you can use that handle to delete it with DeleteObject

http://msdn.microsoft.com/en-us/library/dd162957%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/dd183539%28v=vs.85%29.aspx

jj2007

Not tested, but this should do the job:

   invoke nrandom, 0ffffffh
   invoke CreateSolidBrush, eax
   push eax ; will be arg for DeleteObject
   invoke SelectObject, hDC, eax
   push eax   ; save previous object
   ... draw ...
   pop eax
   invoke SelectObject, hDC, eax   ; select previous object
   call DeleteObject   ; the arg is already on the stack

xroot

My program works fine, I don't care about saving the old brush, just want to know if my way will run out of brushes.(someone said this without any reason why or how)
I have read SelectObject API and have always used it like jj2007 says.
When I execute SelectObject over and over without saving the old brush does creating a new brush each time
use up different brushes each time somewhere in memory??

qWord

xroot,
you are producing a so called 'handle leak' - that is simply a bug and it is a question of time, that your program stop working.
FPU in a trice: SmplMath
It's that simple!

jj2007

Just test it. Create an endless loop, with an invoke Sleep, 1 to prevent problems with your Office suite, and let it run some days. Then report to us what happened.

dedndave

just add one more line...
   invoke nrandom,0ffffffh
   invoke SelectObject,hDC,rv(CreateSolidBrush,eax)
   invoke DeleteObject,eax


deleting unused objects reduces your use of system resources   :U

jj2007

Dave,

that's almost as evil as jmp DefWindowProc :green2

xroot

Thanks, qWord
That is what I wanted to know I will change my code
and again thanks.

http://en.wikipedia.org/wiki/Handle_leak

hutch--

xroot,

> I don't care about saving the old brush

You need to care if you don't want the memory leak. The high level logic is you select an object AND save the old one. Do what you need with the selected object then delete it and restore the old one.

In pseudo code,


    SelectObject newobj
    mov hOldObj, eax
  ; perform what you want with the object.
    DeleteObject newobj
    SelectObject hOldObj


The problem with doing the following,


invoke SelectObject,hDC,rv(CreateSolidBrush,eax)


is you don't save the old brush so every time you call the function you waste more memory.

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

i am playing with something similar - but i am selecting a font, rather than a brush

just a guess, here - it probably takes longer to delete an object than it does to restore the original handle
my thinking is that selecting a font or brush for a DC simply involves placing the object handle in a table that describes the DC
whereas, deleting an object requires more time to free the resources

in my case, i create the font in a routine that allows the user to select fonts
that handle is then stored in a global variable, where it remains unaltered until the user selects a different font
no need to repeatedly create and delete that object

in the paint routine, i select the font object, saving the original (replaced) font handle on the stack
once the paint routine is done, i restore the orignal font with another SelectObject call
i.e., the only time an object is deleted is if the user selects a new font - i delete the old one

your case is a little different, in that you are randomly creating a different object with each pass
it seems you should delete an object, whether it is the original one, or the one you created
however, it seems to be a little more efficient to delete the original object than the one you created
because it requires an additional system call to delete the one you created

Hutch's pseudo-code
    SelectObject newobj
    mov hOldObj, eax
  ; perform what you want with the object.
    DeleteObject newobj
    SelectObject hOldObj


Dave's pseudo-code
    SelectObject newobj
    DeleteObject oldobj
  ; perform what you want with the new object.


the only problem i see is that you might be trying to delete a system-created object
i read something about that on MSDN, but i don't remember what it was - lol - old age
(as i recall, it was either "don't do it" or "the attempt is ignored")
you might want to thoroughly review the SelectObject and DeleteObject documentation to see what the details are

EDIT:
ok - i found a note in the documentation for SelectObject...
QuoteThis function returns the previously selected object of the specified type. An application should always
replace a new object with the original, default object after it has finished drawing with the new object.

unfortunately, they do not explain why or what happens if you don't   :(
your hair may fall out, i guess   :P

what you probably want is something like this
   invoke nrandom,0ffffffh
   invoke SelectObject,hDC,rv(CreateSolidBrush,eax)   ;create the first brush outside the loop
   push   eax                                         ;save the original handle

top_of_loop:
;paint something
;delete the created handle
;nrandom
;create solid brush
;select object
;count and branch to top_of_loop

;delete the last object
;reselect the original one


hutch--

Dave,

There is an easy way to see what happens, put the call in the WM_PAINT for a Window with a looped function and load Task Manager. Start the window and watch it leak like a sieve.

Effectively the OS maintains a "current object" for as many types of objects as are available, for your process it is available until you alter that state by selecting your own object, if you don't restore it in the documented way you don't recover the memory used for your new object.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

qWord

switching to GDI+ avoids these annoying SelctObject()-hell :lol
FPU in a trice: SmplMath
It's that simple!

jj2007

Quote from: dedndave on June 20, 2011, 02:37:17 PM
the only problem i see is that you might be trying to delete a system-created object
i read something about that on MSDN, but i don't remember what it was - lol - old age
(as i recall, it was either "don't do it" or "the attempt is ignored")

You can try but it will be gracefully ignored. This is for lazy programmers like you and me who do not want an extra check if the object is sys or private :bg

Quote
EDIT:
ok - i found a note in the documentation for SelectObject...
QuoteThis function returns the previously selected object of the specified type. An application should always
replace a new object with the original, default object after it has finished drawing with the new object.

unfortunately, they do not explain why or what happens if you don't   :(
your hair may fall out, i guess   :P

Actually, it is a non-trivial question. I tried DeleteObject on a font that was still selected, and it returns sometimes 1, sometimes 0 but in any case "The operation was completed successfully". Hmm... dig further and you find this:

"Do not delete a drawing object (pen or brush) while it is still selected into a DC."

You see? Fonts are not mentioned, hehe! :green2

MichaelW

I seem to recall a post here recently that explained why you should always replace a new object with the original but I can't recall who posted it or find the post.
eschew obfuscation