Crossed memory pointers / cleanup missing ?

edited June 2016 in Questions about Code

My sketch is a little complicated, so it is spread in several .PDE files. I do use the semi-documented surface.setSize(), but otherwise pure Processing Java without any libraries.

The code has a class "Button". It is used quite a lot, even arrays of it. Sometimes, even after a clean restart of Processing, it confuses which button does what, or omits drawing a button. This is in the "first" loop, so it has not done anything fancy. It fails on both 3.0.2 and the latest 3.1.1, both 32bit XP, 32 bit Win7 and 64bit Win7.

The code has worked fine for a while, as I am still developing it. The natural thing is to presume the last change broke it, but that is too difficult to roll back.

I also have had an issue with the debugger ignoring some breakpoints which make me believe I have somehow corrupted memory - or found a bug.

So the question is - am I doing something "subtly" wrong?

Tagged:

Answers

  • edited June 2016

    (The full version of the program is taken offline)

  • edited June 2016

    I have now shortened the program (so now the logic makes little sense) and still have the error.

    Just run the sketch. You do not need to do anything, but can verify the function of the Quit and Filechoice button. Sometimes the quit button has moved on top of the filechoice button. Why?!

    (NB: I swapped the order of .display() of the buttons. This made the quit button visible, and thus explains why the filechoice button acted as a quit.)

        int PhaseState = 0 ;  // Main state, usually involves new display when changing
        int PhaseSub = 0 ;    // Substate of main, but within same module/display
        int PhaseCnt = 0 ;    // Additional state-persistent counter
        int PhaseSolver = -1 ; // Which Solver
        int Solved = 0 ;      // Current Solution state
        Button Btn_Grid ;     // to be able to do input on the grid, it is declared as a button
        Button Btn_Quit, Btn_Stop, Btn_Step, Btn_Run, Btn_Fast ;
        PFont Std ;   // The default font, in bold, for most (button-)text
        PFont Nrw ;   // Narrow Arial
        final int GSZ=12 ;    // Size of a grid cell (and by implication the surround info lines)
        final int ESZ=8 ;     // max number of elements in a line rule
        final int BSZ=GSZ*ESZ ; // Info border size, room for rule display
        int RSZ, CSZ ;
        /*===============*/ void setup() /*=================**
        | Only does the minimal setup, draw() starts other  | 
        **=================================================*/
        {
          size(100,100) ; fill(255,0,0) ;
          text("SPLASH",10,height/2-10);
          surface.setResizable(true);
          frameRate(30) ;
          background(200) ;
          //printArray(PFont.list()) ;
          Nrw = createFont("Arial Narrow",10) ;
          Std = createFont("Source Sans Pro Semibold",13) ;
        }
    
        /*==========*/void draw() /*=============**
        | Simple switch to the subprogram choosen |
        **=======================================*/
        {
          // PhaseSub is reset to 0 on switch,
          switch (PhaseState) {
            case 0: delay(333) ; PhaseState++ ; break ; // Hold here for the initial splashscreen
            case 1: PhaseSolver = LoadChoice() ;
              if ( PhaseSolver == -2 ) { PhaseState = 3 ; Solved = PhaseSolver ; }
              if (PhaseSolver>=0) //  data structures loaded with puzzle. return value is choice.
              {PhaseState++ ; PhaseSub=0 ;} break ;
            // case 2 thru 6 all return <0 for abort/fail, >0 for success. =0 to keep looping.
            case 2: // keep calling the solver when return =0, 
                    // else <0 for abort/fail, >0 for success
              switch(PhaseSolver) {  // ( same numbering as "Choice_Desc" in LoadChoice ) 
                case 0: Solved = 1 ; break ;
                case 1: Solved = 1 ; break ;
                case 2: Solved = 1 ; break ;
                case 3: Solved = 1 ; break ;
                case 4: Solved = 1 ; break ;
                default: print("Illegal Solver") ; exit() ;
              }
              if (Solved!=0) {PhaseState++ ; PhaseSub=0 ;}
              break ;
            case 3: Draw_End(Solved) ;      // for now, it is only called once 
              {PhaseState++ ; PhaseSub=0 ;} break ;
            case 4: exit() ; break ;
            default: print("Illegal PhaseState"); exit() ; 
          }
        }
    
        void Draw_End(int S) { println("*nDraw End with ",S); }
    
    
        /*=========*/ class Button /*===============*/
        {
          int xl, xh, yl, yh ;  // Location of button, 2 diagonal corners
          String Lbl ;          // Text in button
          color Col ;           // Colour
          private int State, lastState ;  // mouse press state
          private boolean Right ;         // -"-
          Button(int XX, int YY, int XW, int YH, String LBL, color COL) {
            xl = XX ; xh = XX+XW ; yl = YY ; yh = YY+YH ;
            Lbl = LBL ; Col = COL ;
            State = 0 ; lastState = State ; Right = false ; // Non-pressed
          }
        /*=========*/ void setPos(int XX, int YY, int XW, int YH) 
        {
            xl = XX ; xh = XX+XW ; yl = YY ; yh = YY+YH;
            display() ; // display it in new position
          }
        /*======*/ void setCol(color COL)  /*====*/
        {
            Col = COL ;
            display() ; // display it with new color
          }
        /*======*/ void setLbl(String LBL) /*======*/
        {
            Lbl = LBL ;
            display() ; // display it with new label
          }
        /*======*/ void display() /*======*/ 
        { 
          // draw the button (common part)
          print("["+Lbl+"]");
            pushStyle() ;
            fill(Col); noStroke() ; 
            rect(xl,yl,xh-xl,yh-yl) ;
            fill(0) ;  textFont(Std) ; text(Lbl,xl+1,yh-3);
            popStyle() ;
          }
        /*======*/ int check() /*======*/
        {
          // updates state depending on mouse and return it
          lastState = State ; State = 0 ;
          if (xl <= mouseX && mouseX <= xh && yl <= mouseY && mouseY <= yh) 
            if (mousePressed) { State = 2 ; Right = mouseButton==RIGHT ; }
            else State = 1 ;
          if ( State ==2 && lastState == 2 ) return 3 ; else return State ;
          }
        }
    
        Button Btn_File ;
        Button[] Btn_Choice ;
        String[] FileNames = { "Pic0.txt", "Pic1.txt", "Pic2.txt" } ;
        int ChooseFile = 0 ;
    
        /*=============*/ int LoadChoice() /*================*/
        {
          int ChoiceN = -2 ;
          String[] Choice_Desc = { "Manual", "BinaryScan", "Shuffle Blocks", "Algorithmic", "Genetic" } ;
          int NN ;
    
        /*======*/if (PhaseSub==0) /*======*/
        {
          print("*nLoadChoice-Initialse") ;
          surface.setSize(200,100) ;
          Btn_File = new Button(10,80,55,14,FileNames[ChooseFile],color(100,100,150) ) ;
          Btn_Quit = new Button(10,height-20,30,13,"Quit",color(200,50,50)) ;
          Btn_Choice = new Button[5] ;
          String[] BtnNames = { "Man", "Bin", "Shf", "Alg", "Gen" } ;
          for ( int n=0; n<5; n++ )
            Btn_Choice[n] = new Button(10+n*36,15,30,14,BtnNames[n],color(100,100,150) ) ;
          // end of initialse phase 1, dont do it again. Return immediatly for resize
          PhaseSub = 1 ;
          return -1 ;
        }
        /*======*/if (PhaseSub==1) /*======*/
        {
          // Second initialisation. Draw static parts
          Btn_File.display() ;
          Btn_Quit.display() ; //<>//
          for ( int n=0; n<5; n++ ) Btn_Choice[n].display() ; 
          // end of initialse phase 2, dont do it again
          PhaseSub = 2 ;
          println("..done") ;
          return -1 ;
        }
    
    
        /*=====  Mouse actions =========*/
          // handle "mouse over" of the solver selection button
        /*
          NN = -1 ;
          for ( int n=0; n<5; n++ ) { 
            if ( Btn_Choice[n].check()==1 ) {
              Btn_Choice[n].setCol(color(200,100,100)) ;
              fill(0) ; text(Choice_Desc[n],10,35+10);
              NN = n ;
            }
            if ( Btn_Choice[n].check()==0 ) { 
              Btn_Choice[n].setCol(color(100,200,100)) ;
            }
            if ( NN == -1 ) { fill(200) ; noStroke() ; rect(10,35,90,20) ; }
          }
          // handle an actual selection of solver
          for ( int n=0; n<5; n++ ) 
            if ( Btn_Choice[n].check()==3 ) {
              PhaseSub = 3 ;
              ChoiceN = n ;
              println(ChoiceN," choosen");
          }
        */
          // handle the file selection
          // Currently simplified - cycles through 3 hardcoded filenames
          if ( Btn_File.check()==2 ) {
            ChooseFile = (ChooseFile>=2)?0:ChooseFile+1 ;
            Btn_File.setLbl(FileNames[ChooseFile]) ; 
          }
    
          // handle the quit button
          if ( Btn_Quit.check()==2 ) return -2 ;
    
        /*====*/ if (PhaseSub==3) /*===== Load action =*/
        {
          RSZ=10;CSZ=15;
          // Register grid area as one button
          Btn_Grid = new Button(BSZ, BSZ, GSZ*CSZ, GSZ*RSZ,"GRID",color(100,100,0)) ;
          return ChoiceN ;
        }
          // LoadChoice done, call again
          return -1 ;
        }
    

    There is no code that moves the Quit button. The initialisation is fixed.

Sign In or Register to comment.