News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Easy way to destroy stuff in a program

Started by NoCforMe, December 20, 2014, 11:40:02 AM

Previous topic - Next topic

hutch--

It reduces down to a person thinking that they know more about an operating system than those who created it. When an OS vendor documents a set of functions, its because they know how they work and when they recommend a set of procedures to clean up after allocating resources, it is so the OS remains stable and the application continues to run correctly without using up more resource than it needs.

It boils down to whether you every write anything that matters, if you do then you have little option than to be tidy in what you write cleaning up any mess you make on the fly in the correct scope. If what you write does not matter, then who cares. The only reason why a question and set of suggestions of this type are made is sheer lazyness, why do it the right way as specified by the OS vendor when you can be sloppy and write rubbish.

The combination of SelectObject() and DeleteObject() are done for a reason, behind the GDI functions is very high level code that is much more complex that simplistic assumptions make out. You select and object while saving the old object handle, use what you need then reselect the old object then delete the new one. This way the system is not being burdened by wasted resource and your app if its doing anything more than trivial remains stable.

jj2007

Quote from: hutch-- on December 22, 2014, 07:42:16 PMThe combination of SelectObject() and DeleteObject() are done for a reason, behind the GDI functions...

Hutch,

There are no contradictions to what you are writing:
Quote from: adeyblue on December 22, 2014, 04:57:29 PMAll you need to reset is the stuff returned from SelectObject (except regions), for the reasons outlined above. At least, all these GDI docs were written at the same time, and the only one that mentions it is SelectObject.

We all agree on that, and it's also pretty obvious that e.g. SetTextColor and SetBkColor don't fall into this category. Interesting adeyblue's point on regions btw.

What is less obvious is the habit of carefully destroying objects before throwing them into the dustbin of ExitProcess. The documentation is somewhat vague on this point, unfortunately. It would be in the good tradition of the Masm32 Forum to test it empirically, by launching a Million little apps and testing if
- fonts
- bitmaps
- system strings
- GlobalAllocs
- VirtualAllocs
- ...
all belong to the same category "gone once the process is gone", or whether some belong to the category "global resources, to be treated differently". This is badly documented by Microsoft, and my own experience tells me that, in contrast to the rule "process dead means all memory is released", it's not that simple. For example, badly crashing an app that has hundreds of megabytes heapalloc'ed may result in slowing down the system - which is illogical because Windows should clean up the mess but... ::)

And again, the question is whether this is limited to processes that are ended "exceptionally" (pun intended), and whether the same can happen with ExitProcess, too (which I doubt, but damn, where is the documentation that treats this in non-ambiguous language??).

The same doubts I have on fonts, because I have seen occasionally that after heavy testing the whole system had difficulties with fonts. If Notepad uses SYSTEM_FIXED_FONT in menus, then something has gone wrong. It shouldn't, with an OS that claims to safely separate all applications since the days of NT, but it does happen.

Tedd

It's not strictly necessary to return the DC back to its exact original state; the point is to not leave any allocated objects selected into the DC.
The DC is initialised with a set of stock objects (system allocated and persistent.) Each time you call SelectObject, the previous object of the same type is returned, and in the case of a fresh DC that will be a stock object (assuming your DC is not shared.)
So, as long as you leave the DC with a set of stock objects, there should be no problems. To do this, you have the option of simply restoring the objects returned by calls to SelectObject, or by retrieving stock objects of the same type with GetStockObject -- the result will be the same.

The reason the GDI is this way comes from the early versions of Windows, where DCs were a shared resource, and so you would have to leave a DC in the exact state you found it so that you wouldn't mess up another process' graphics. DCs are no longer shared by default, so there is no strict obligation to return the DC to its original state.
It is arguable that there's no need to even de-select objects from the DC (though it definitely was necessary up until Windows XP), but this is the same argument as "it's not necessary to close file handles because the OS will close them on exit." You should. The OS tries to clean up to cover for exceptions, where a process wouldn't have had the opportunity to clean up correctly itself; it is not an excuse to be lazy.

You can choose to write sloppy code because you think you're saving a few function calls (you're not, the OS will still have to call them on your behalf), but what is the benefit?
Potato2

NoCforMe

QuoteIt's not strictly necessary to return the DC back to its exact original state; the point is to not leave any allocated objects selected into the DC.

So, would something like this make y'all happier?

do_paint:
...
INVOKE SelectObject, hDC, OpOutputFontHandle
MOV prevFont, EAX
...
INVOKE TextOut, hDC, $opOutputOffsetX, $opOutputOffsetY, OFFSET OpString, EDX
INVOKE SelectObject, hDC, prevFont
INVOKE EndPaint, hWin, ADDR ps
XOR EAX, EAX
RET
Assembly language programming should be fun. That's why I do it.

dedndave

i generally try to double-buffer
that makes a difference, because you are not modifying a DC related to a physical device
instead, you are modifying a memory DC

the other thing is - SaveDC and RestoreDC take out the headaches
this is an example - double-buffered using SaveDC/RestoreDC....

http://masm32.com/board/index.php?topic=3344.msg35250#msg35250

if you read that thread in it's entirety, you might find something useful