Announcement

Collapse
No announcement yet.

Strange TreeView Crash Bug

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

  • Strange TreeView Crash Bug

    And it is really strange to see what's happening with the message pump at selected points that seems to lead up to the crash. The crash does not happen in debug mode, just when running the compiled executable.

    The program is designed to open up a file of images, it constructs the treeview to show a list of said images in the file. This all works nicely. However, I can open one file after another, and the treeview resets properly, and reloads without causing a boom. It's when I make a selection on the treeview to make the associated image that the boom will happen shortly thereafter when I open another file.

    It seems that after I make that initial selection click in the treeview, the reset and reload will send a succession of %TVN_SELCHANGED notifications to the main dialog window, and I'm not certain if that's supposed to happen. This is also resulting in every selection causing the program to attempt to display the selected image, and probably on my fault, I'm not checking bounds, so it goes boom.

    I am going to code around this behavior, I'm just wondering if it's something I'm supposed to do, or is something that I'm going to have to do due to the succession of %TVN_SELCHANGED codes being sent. I don't see a means from the SDK on clearing a selection from a treeview, ...

    P.S. Using DDT;
    Code:
         CONTROL ADD "SysTreeView32", hDlg, %IDTV_FOXTREE, "FoxTree", 6, 254, 126, _
            149, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %TVS_HASBUTTONS OR _
            %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS OR %TVS_FULLROWSELECT OR _
            0, %WS_EX_CLIENTEDGE OR %WS_EX_ACCEPTFILES OR _
            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    Last edited by colin glenn; 22 Feb 2009, 01:13 AM. Reason: forgot to mention create
    Furcadia, an interesting online MMORPG in which you can create and program your own content.

  • #2
    The crash does not happen in debug mode, just when running the compiled executable.
    That's a dead giveway.

    First, it tells us you are not compiling with #DEBUG ERROR ON.

    Second , it tells us you should be, becuase "somewhere" in your program you are either exceeding an array bounds or passing a null pointer.

    Running in the stepping debugger, #DEBUG ERROR ON is automatic; and when #DEBUG ERROR ON is true, statements attempting to violate array bounds or use a null pointer are not attempted. (Instead the system ERR value is set to 9).

    However, you *should* be seeing that "Error 9" in the stepping debugger's output window when this happens.

    I don't see a means from the SDK on clearing a selection from a treeview, ...
    Syntax
    Code:
    BOOL TreeView_SelectItem(
        HWND hwndTV,
        HTREEITEM hitem
    );
    Parameters

    hwndTV
    Handle to the tree-view control.
    hitem
    Handle to an item. If the hitem parameter is NULL, the control is set to have no selected item.
    First thing you do is compile your executable with #DEBUG ERROR ON and run. If it does not "crash" (whatever that means, I am assuming you mean 'program terminated due to a General Protection Fault' ), then for sure your problem is the use of an invalid array subscript or a null pointer. Then comes the fun part: actually finding it.



    MCM
    Last edited by Michael Mattias; 22 Feb 2009, 09:55 AM.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Colin --

      If you run your program in the debugger and add BREAK ON ERROR option, the debugger will stop as soon as an error is detected.

      Bob Zale
      PowerBASIC Inc.

      Comment


      • #4
        Thanks Bob.
        Missed one of my bound checks:
        Code:
        PROPERTY GET ComboPosition(BYVAL ShapeIndex AS LONG, BYVAL FrameIndex AS LONG) AS DWORD
            IF ShapeIndex <= UBOUND(Shapes) THEN _
                 IF ISTRUE ISOBJECT(Shapes(ShapeIndex)) THEN _
                     PROPERTY = MAK(DWORD, _
                         Shapes(ShapeIndex).PositionX(FrameIndex), _
                             Shapes(ShapeIndex).PositionY(FrameIndex))
        END PROPERTY
        However, I still find it odd that resetting the treeview causes %TVN_SELCHANGED to be sent to the parent dialog for each of the elements ABOVE the selection:
        Code:
        ' snippets
        ' in main
        CASE %IDM_menuFileOpen
            IF ISTRUE LoadFile(CB.HNDL) THEN
                #DEBUG PRINT "Open File"
                isLoading = %TRUE
                LoadFoxList CB.HNDL, %idtv_foxtree, Fox
                isLoading = %FALSE
            END IF
            procResults = 1
        ' -----
        ' also in main
        CASE %WM_NOTIFY
          ' IF ISTRUE isLoading THEN EXIT FUNCTION
          SELECT CASE CB.NMID
            CASE %idtv_foxtree, %idtv_importtree
              IF CB.NMCODE = %TVN_SELCHANGED THEN
                LOCAL pnmtv AS NM_TREEVIEW POINTER
                pnmtv = CB.LPARAM
                SELECT CASE CB.NMID
                  CASE %idtv_foxtree
                    SetCurrentShape CB.HNDL, CB.NMID
                    Work = IIF$(@pnmtv.action = %TVC_BYKEYBOARD, "Keyboard", _
                      IIF$(@pnmtv.action = %TVC_BYMOUSE, "Mouse", "Unknown"))
                    #DEBUG PRINT "Selection by "& Work _
                      &"-"& FORMAT$(CurrentShape) &":"& FORMAT$(CurrentFrame)
                    memBit = MakeFshBitmap(CurrentShape, CurrentFrame, Fox)
                    CONTROL SEND CB.HNDL, %idf_imagedisplay, %UM_SETIMAGE, _
                      memBit, Fox.ComboPosition(CurrentShape, CurrentFrame)
                    ' there IS code in the rest of the system that does check for
                    ' invalid objects of any sort
        ' -----
        ' in LoadTreeView
        ' ...
        #DEBUG PRINT "Resetting Treeview"
        TREEVIEW RESET hDialog, hTree
        #DEBUG PRINT "Treeview Reset"
        ' ...
        IF FrameN = 0 THEN
            ' parent item
            TREEVIEW INSERT ITEM hDialog, hTree, 0, %TVI_SORT, pThumb, cThumb, Work TO ShapeTree
            #DEBUG PRINT "Loaded Parent :"& FORMAT$(ShapeN) &":"& FORMAT$(FrameN) &":"& FORMAT$(ShapeTree)
        ELSE
            ' child item, expect ShapeTree to be valid
            TREEVIEW INSERT ITEM hDialog, hTree, ShapeTree, %TVI_SORT, pThumb, cThumb, Work TO ChildTree
            #DEBUG PRINT "Loaded Child :"& FORMAT$(ShapeN) &":"& FORMAT$(FrameN) &":"& FORMAT$(ChildTree)
        END IF
        
        ' --- after the for/next is done ---
        TREEVIEW SET IMAGELIST hDialog, hTree, iList
        #DEBUG PRINT "Attached Imagelist"
        All that above so the below makes sense:
        Code:
        Begin Debug at 12:35:51 PM on 2/22/2009
        Open File
        Resetting Treeview
        Treeview Reset
        Loaded Parent :0:0:30095712
          Loaded Child :0:1:31059584
          ...
          Loaded Child :0:7:31060128
        Loaded Parent :1:0:31060272
          Loaded Child :1:1:31060384
        ...
        Loaded Parent :45:0:31467496
        Attached Imagelist
        Selection by Mouse-17:0
        Selection by Mouse-29:1
        Selection by Keyboard-30:0
        Open File
        Resetting Treeview
        Selection by Unknown-31
        ...
        Selection by Unknown-45
        Treeview Reset
        Loaded Parent :0:0:12908368
        ...
        Loaded Parent :6:0:29167672
        Attached Imagelist
        End Debug at 12:38:48 PM on 2/22/2009
        So, on reset, what is sending the %TVN_SELCHANGED to the main dialog? Apparently the handle to the selected element is still valid because SetCurrentShape uses the handles passed to it to set the CurrentShape variable.
        Furcadia, an interesting online MMORPG in which you can create and program your own content.

        Comment


        • #5
          "Treeview Reset" must result in TVN_SELCHANGED, because when content is emptied, and previous selection is perforce eliminated.

          Not to mention "SetCurrentShape" (code not shown) or possibly but not likely "CONTROL SEND CB.HNDL, %idf_imagedisplay, %UM_SETIMAGE" (code not shown).

          Don't know what those do.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            SetCurrentShape:
            Code:
            ' assume valid variables
                TREEVIEW GET SELECT hDialog, idControl TO cSelected
                TREEVIEW GET TEXT hDialog, idControl, cSelected TO sSelected
                TREEVIEW GET PARENT hDialog, idControl, cSelected TO cParent
                IF ISTRUE cParent THEN
                    TREEVIEW GET TEXT hDialog, idControl, cParent TO sParent
                    CurrentShape = VAL(PARSE$(sParent, "-", 1))
                    CurrentFrame = VAL(sSelected)
                ELSE
                    CurrentShape = VAL(PARSE$(sSelected, "-", 1))
                    CurrentFrame = VAL(PARSE$(sSelected, "-", 2))
                END IF
            So if the function can get the text of the selected treeview node, then the node is still valid at this point. The crash comes from the CONTROL SEND when it calls on the Fox property ComboPosition and it might be referencing an invalid position in the array of objects because at this point, the array had already been cleared, reset, and loaded with new values. If the new array had more elements than the old array, no problem, but if the new array had less elements than the old one, then it would it generate a "out of bounds" error. Hence, my forgetting to check bounds in ComboPosition was my error because I did not expect this behavior to occur with the TREEVIEW RESET sending %TVN_SELCHANGED to the main dialog on each element being deleted from the treeview.

            P.S. %idf_imagedisplay is a custom winproc / control for handling the image to be displayed.
            Furcadia, an interesting online MMORPG in which you can create and program your own content.

            Comment


            • #7
              >TREEVIEW GET SELECT hDialog, idControl TO cSelected

              Probably not the case here, but in general you should check 'cSelected' for "no selection." (value zero) and not attempt TREEVIEW GET TEXT when that is the case. (This may not be possible in your app, eg, function is never called unless there is a selection.. but in that case I'd probably be passing 'cSelected' as a parameter to this function, since I would have had to get that value anyway just to decide if something was selected).

              The compiler and/or operating system may cover this error here, but no sense not testing yourself if you can.

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                That is a good point, even though the function is not called unless there was a selection, no sense in tempting fate against the oddball instance when GIGO happens.
                Furcadia, an interesting online MMORPG in which you can create and program your own content.

                Comment

                Working...
                X