Announcement

Collapse
No announcement yet.

Mystery of Shrinking Resources

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mike Jenkins
    Guest replied
    Ah, yes, thanks Chris, and Lance.

    As you point out, Chris, that's probably what was wrong
    in my program, as I was not bothering to determine if the
    2nd and 3rd dialogs I was simultaneously sending stock ticker
    strings to were active, destroyed, or not even created yet for
    a first time. The remedy I used was as you suggested, Lance,
    to use GLOBAL on/off variables to keep track of the 3 dialogs,
    and only send text to the "live" ones from my stock ticker SUB.
    Which seems to have cured the problem.

    In any case, thanks for all your help and suggestions. The
    "bleeding" has stopped, and the torpedoes are running hot,
    straight, and normal now, so to speak.

    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    That all sounds logical Chris. Good programming practice indicates that you should track your active and destroyed controls, and only send messages to the active ones.

    For example, suppose that you use global variables to track the handles of these controls, it is a simple matter to set these variables to zero when the controls are destroyed (say, during %WM_DESTROY in the dialog callback) and test the variable before sending a message.
    Code:
    'pseudocode
    GLOBAL hControl1 AS LONG
    GLOBAL hControl2 AS LONG
    GLOBAL hControl3 AS LONG
    ...
    IF hControl1 THEN _
      SetWindowText hControl1, "the text" ' or send %WM_SETTEXT, etc
    ...
    CASE %WM_INITDIALOG
      CONTROL GET HANDLE CBHNDL, %ID_CONTROL1 to hControl1 
    ...
    CASE %WM_DESTROY
      hControl1 = 0
    BTW, a little tip for you:
    when sending messages to a control using it's handle (rather than CONTROL SEND using it's ID), you can use DIALOG SEND:

    For example:
    Code:
    CONTROL ADD LABEL, hDlg&, 100, "Btn1", 10, 10, 80, 14
    ...
    CONTROL HANDLE CBHNDL, 100 TO hCtl&
    a$ = "new text"
    DIALOG SEND hCtl&, %WM_SETTEXT, 0, STRPTR(a$)
    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Chris Boss
    replied
    I couldn't tell from your post whether the other dialogs were just
    hidden or they didn't exist, when not visible.

    If the they didn't exist, when not visible, you would definitely have a
    problem, since the handles no longer are valid (for the Dialog).

    You would be sending erroneous messages to handles which could
    now possibly be assigned to a new window or control (I am sure Windows
    reuses handle numbers once they are available again).

    It is possible to send messages to hidden Dialogs/Controls so I doubt
    that would be a problem, unless the label control doesn't like
    being inundated with messages when it is hidden.


    ------------------

    Leave a comment:


  • Mike Jenkins
    Guest replied
    Mystery solved.... Sort of. I "fixed" the disappearing resources
    problem (or at least reduced the "leakage" to virtually nil, even
    after 4 or 5 hours of running the simulation hard). But don't
    really have a good explanation for the fix. All I changed was
    as follows:

    Before I changed it, my stock market/takeover simulation ran
    a simulated stock ticker, which it "printed" to a label control
    on all 3 of the main program screens, whether or not all of them
    were visible to the user. I simply modified the code that
    updates the ticker controls so that only the VISIBLE screens
    (usually 1, sometimes 2) are updated several times per second,
    to create the illusion of a moving stock ticker on each.

    It seems that updating all 3 screens (dialogs), even when some
    were no longer in existence, somehow caused a steady and major
    loss of Windows resources (of all 3 types, GDI, User, and System).
    Updating only the visible dialogs seems to have halted about
    99% of the "leakage." Wish I had a clearer answer, but thanks
    for all the input, anyway, guys.

    ------------------

    Leave a comment:


  • Chris Boss
    replied
    Mike;

    A Windows app only needs one Message Loop !

    Following SDK style message loop coding, I use the simple Doevents
    loop described above, the same way I do a message loop in SDK style
    code.

    You create your main dialog first (in PBMain) and then execute the
    doevents loop (see above). You don't need any more doevents loops.

    You should (IMO) make the first Dialog modeless and then others can
    be either modeless or modal. When you use a modal dialog, it won't use
    the Doevents loop in PBMain. It will use a separate message loop
    generated by Windows itself (if DDT uses the Window modal engine).



    ------------------

    Leave a comment:


  • Mike Jenkins
    Guest replied
    <<
    ' use this code in PBMain
    DO
    DIALOG DOEVENTS TO Count&
    LOOP UNTIL Count&=0
    ' app can now terminate by exiting PBMain
    >>

    Ah, got it, finally. (Cogito.) However, I've been using a
    modal main dialog, since I contrived to use a (hidden) modeless
    dialog to run the moving stock ticker in my simulation, until a
    user clicks on something and triggers an exit from the DOEVENTS
    loop, and thus halts the ticker.

    I was hesitant to try to use a second DOEVENTS loop in my main
    dialog, since I was unsure of whether it was possible to have
    two DOEVENTS loops running at once. But I assume you mean to
    put the above loop in PBMAIN to run only AFTER ending the main
    dialog? (Or does that cause a problem if all dialogs are closed
    at that point, as the PB/DLL manual suggests? "DO NOT call
    DIALOG DOEVENTS unless at lest one dialog created with DIALOG
    NEW is active." I.e., meaning it must be part of the main
    dialog itself?)



    ------------------

    Leave a comment:


  • Chris Boss
    replied
    Mike;

    Some messages for closing a Dialog come through the WM_SYSCOMMAND
    (%SC_CLOSE) message rather than the WM_CLOSE message. Try checking
    it too.

    Also, if a Dialog is a Child (floats above its parent) then when its
    parent Dialog is closed, Windows should automatically close the child.

    Also, assuming the main dialog is modeless, you should have a message
    pump loop in PBMain that tests for the number of active Dialogs, so
    the app doesn't terminate until all the Dialogs have been destroyed.

    Code:
        ' use this code in PBMain
        DO
            DIALOG DOEVENTS TO Count&
        LOOP UNTIL Count&=0
        ' app can now terminate by exiting PBMain


    ------------------

    Leave a comment:


  • Mike Jenkins
    Guest replied
    Thanks, Russ. There seem to be a lot of possibilities. I don't
    use the timer in my program, so that's probably not my bug.

    I think I've narrowed down the problem similar to the one you
    describe, though, but I'm still trying to find a way to trap or
    prevent it. It seems that when a child dialog (call it Dialog2
    Dialog3) is left open at the time I exit the program, if I exit
    the program by clicking on my "QUIT" button or "EXIT" on the
    File Menu, I can successfully trap that situation by using
    DIALOG END Dialog2, etc., so that the program terminates cleanly.

    However, if I exit by double-clicking the System Menu box while
    Dialog2 or Dialog3 is open, I get the same kind of "dirty" exit
    you describe. Strange. I've tried trapping the %WM_CLOSE
    message, inserting a "Are you sure you want to quit?" message
    box, and, if confirmed, using DIALOG END for any open child
    dialogs, such as Dialog2, but that seems to have no effect.

    Yet another mystery for a newbie programmer, who's only been
    at this about 8 months. I'm tempted to just get rid of the
    System Menu boxes, although that's probably considered to be
    non-kosher, and seems a bit like throwing out the baby with the
    bathwater.




    ------------------

    Leave a comment:


  • Russ Srole
    replied
    Mike,

    I had one of those problems where sometimes when I closed the program
    it would disappear from the desktop, but actually still be in memory.
    I am using a windows timer to do do some background routines, and
    forgot that you should shut that down when you initiate your end
    program procedures. So now I turn off that timer first thing and
    it closes properly every time.

    Russ Srole

    ------------------

    Leave a comment:


  • Mike Jenkins
    Guest replied
    Thanks for all the feedback, everyone. I'm going to try several
    of the suggested approaches, and if one of them solves the
    problem, I'll post the results here on the Forum, if it was
    something wrong with my code, rather than a problem inherent
    in Windows.

    ------------------

    Leave a comment:


  • Chris Boss
    replied
    I ran Mikes program on Windows 95 (OSR1) and I sent him the results.

    My impression is that there is no Resource leak in his code. I think he
    is pushing the Label (or textbox) control which displays the Ticker Tape
    beyond its limits and that Windows may have a problem in keeping up
    with the rapid changes over a long period of time.

    No leaks show up in 5 or 10 minutes, so I doubt there is a serious
    leak produced by his code. It is possible the leak is produced over
    time as the control that handles the Ticker Tape may eventually begin
    to produce leaks with allocating Global Windows memory for the text
    string.


    My suggestion is to replace the Window control he uses for the Ticker Tape
    with a custom window class and to do the drawing himself.

    Now, if the leak does appear quickly on other operating systems , then
    it is possible it is an issue with the new OS (ME, 2000).

    Simply put, the culprit is most likely the control used for the
    Ticker Tape display.



    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    Scott, that sounds like you were SENDing a message to the dialog rather than POSTing it... depending on the context of the message that triggered the SendMessage, you can get these kind of problems.



    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Scott Slater
    replied
    I had a similar problem one time when I was making a DIALOG END
    call within a message handler under a custom (MY_MESSAGE = WM_USER + x)
    message ID. I found that by ending the program there, that it stayed
    in memory so what I had to do is post another message that would re-direct
    the call to WM_COMMAND and process the DIALOG END from there. I don't
    know why it did that but by re-directing the message the problem was cured.


    Scott





    ------------------

    Leave a comment:


  • jcfuller
    replied
    Chris / Dominic,
    What ver(s) of commctrl.dll were tested??

    James


    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Mike,

    A long time ago when I was learning GDI coding I found a technique
    for tracking down dead BMP resources that were not released properly,
    I used a toy from the SDK called "heapwalker" and opened up the list
    and went looking for the dea remains of bitmaps.

    As Lance mentioned there are some nice toys for finding leaks but
    you have to buy them and learn to fly them as well. It may be worth
    testing and code that is being looped and if possible, try commenting
    out bits of it to see if you can isolate the area of code where the
    leak comes from.

    GDI can be one source of memory leaks but there can be others as well,
    allocated memory that is not released properly can really add up
    as a program runs for any length of time. Just make sure you are
    creating and destroying the controls you are using in the correct manner
    as this may be one of the problems.

    I am sure Chris will help you as you are using his EZGUI as it is likely
    to be a very simple thing that just happens to be in loop code somewhere
    within the application.

    Good Luck with it.

    [email protected]

    ------------------

    Leave a comment:


  • Dominic Mitchell
    replied
    Tests I have done on the toolbar control support what Chris said. Rapidly
    creating and destroying toolbars that use the system bitmaps in commctrl.dll
    produces a nasty leak in GDI resources. To make matters worse the resources are
    not restored even after the application terminates. Toolbars that do not use the
    system bitmaps do not exhibit this problem.
    I cannot think of a single common control supplied by Microsoft that does not
    have a plethora of bugs.

    ------------------
    Dominic Mitchell

    Leave a comment:


  • Chris Boss
    replied
    James;

    I did extensive testing of the Common Control Toolbars and I found
    the Resource leak when using the builtin bitmaps. I haven't seen
    anything in print about it on the MS web site, but that doesn't mean
    it doesn't exist.

    The reason most programmers would fail to notice it, is because
    it only loses a small amount of GDI resource memory and is easily
    missed. The reason I came across it, is because I build Visual
    Designers and it is possible to create and destroy dozens of toolbars
    over and over again. When the Toolbar is created and destroyed multiple
    times, you will then notice the leak begins to build until you run
    out of Resource memory.

    I have sufficiently proved this to myself and I have no doubts
    about it. When I use a external Bitmap for the Toolbars and
    create and destroy them over and over again, the resource leak
    does not exist.

    Let me just say, that I do exhaustive tests when building software.

    Rule of Thumb : The Operating System is not bullet proof !


    ------------------


    [This message has been edited by Chris Boss (edited June 04, 2001).]

    Leave a comment:


  • Bern Ertl
    replied
    Gentlemen,

    I encountered a similar situation early on in my learning curve,
    perhaps Mike is making the same mistake I made.

    Mike, check your code for the following situation:

    1) You have a SUB or FUNCTION (procedure)
    2) That procedure creates a dialog, assigns a dialog callback
    3) dialog callback terminates dialog (DIALOG END)
    4) procedure does NOT realize dialog has ended and runs
    in infinite loop.

    Just because a dialog ends doesn't mean that your SUB or
    FUNCTION which created the dialog will automatically terminate.



    ------------------
    Bernard Ertl

    Leave a comment:


  • Chris Boss
    replied
    Mike;

    If you email me a copy of the actual program (EXE, not source), I
    will test it out for you.

    mailto:[email protected][email protected]</A>

    I doubt the code generated by the EZGUI Freeware Designer is the cause
    since it simply generates DDT Dialog and Control creation commands
    and thats it. Also the Designers code creates brushes upon startup
    and releases brushs upon termination of the app. They aren't created
    during execution.

    Also your problem may be more than one problem, so the app failing
    to terminate may not even be associated with the resource leak.

    When you look at the code in PBMAIN generated by my Visual Designer
    you can see that it creates resource during startup and then releases
    them after the messageloop terminates :

    Code:
    FUNCTION PBMAIN
        LOCAL Count&
        LOCAL CC1 AS INIT_COMMON_CONTROLSEX
    
        CC1.dwSize=SIZEOF(CC1)
        CC1.dwICC=%ICC_WIN95_CLASSES
        InitCommonControlsEX CC1
        EZLIB_DefColors
        EZLIB_InitFonts
    
        ShowDialog_Form1 0
        DO
            DIALOG DOEVENTS TO Count&
        LOOP UNTIL Count&=0
    
    
        EZLIB_DeleteBrushes
        EZLIB_DeleteFonts
    END FUNCTION
    The Do Loop in PBMain, I believe is the proper way to test for
    the applications termination.

    The code above assumes your first DIalog is Modeless, which it should
    be. The first Dialog shouldn't be Modal.




    ------------------

    Leave a comment:


  • jcfuller
    replied
    Originally posted by Chris Boss:


    One example is the Toolbar control. When you use the default bitmaps
    for the toolbar that are built into the Common control DLL, there is
    a resource leak produced by it.

    Also when the data in a control is changed constantly, the control will
    be reallocating Global memory (using the API memory functions)
    every time you change the data (such as window text). Some controls
    may handle this repeated change over and over again better than others.
    Some controls may not take well to repeated changes and it is possible
    for the control to produce a memory leak in such instances.


    Interesting. Do you have the knowledge base Id's for these.

    James




    ------------------

    Leave a comment:

Working...
X