DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L1894
Version: 1.1-current





Link: http://www.fltk.org/str.php?L1894
Version: 1.1-current
/*
===============================================================
  compile and link with: fltk-config --compile crash_1.cxx
===============================================================
*/
  
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Widget.H>

#include <FL/fl_message.H>

#include <stdio.h>

class My_Input;

Fl_Window *window;
Fl_Group *group;
Fl_Button *button1;
Fl_Button *button2;
My_Input *input1;
My_Input *input2;

#define KBS 1024                        // modify: 1=okay, 1024=crash

class My_Box : public Fl_Box {

  int   ref;                            // ref. count
  int   idx;                            // box index

  int   dummy_array[1024*KBS];          // allocate <KBS> KB memory

public:

  My_Box (int, int, int, int, char *, int);
  ~My_Box();

};

My_Box::My_Box (int X, int Y, int W, int H, char *L, int I)
: Fl_Box (X,Y,W,H,L) {

  align (FL_ALIGN_INSIDE);
  ref   = 1;                            // ref. count
  idx   = I;                            // box index

}

My_Box::~My_Box () {

  printf (">>> ~My_Box(%s[%d]): this=%p, ref=%d, 
parent()=%p\n",label(),idx,this,ref,parent());
  printf ("    group %p has %d children\n",group,group->children());
  fflush(stdout);
  ref--;
  if (ref < 0) fl_alert("My_Box %s[%d] deleted more than once: ref = 
%d",label(),idx,ref);
  printf ("--- ~My_Box(%s[%d]): this=%p, ref=%d, 
parent()=%p\n",label(),idx,this,ref,parent());
  fflush(stdout);

}

class My_Input : public Fl_Input {

  My_Box        box1;
  My_Box        *box2;
  
  int           ref;                    // ref. count

public:

  My_Input (int, int, int, int, char *);
  ~My_Input();

};


My_Input::My_Input (int X, int Y, int W, int H, char *L)
: Fl_Input (X,Y,W,H,L), box1(X+W+1,Y,H,H,L,1) {

  box1.box(FL_THIN_DOWN_BOX);
  box1.color(FL_RED);

  box2 = new My_Box(X+W+H+2,Y,H,H,L,2); // 2nd box
  box2->box(FL_THIN_UP_BOX);
  box2->color(FL_GREEN);

  ref   = 1;                            // ref. count

}

My_Input::~My_Input () {

  printf (">>> ~My_Input (%s): ref = %d, parent()=%p\n",label(),ref,parent());
  printf ("    group %p has %d children\n",group,group->children());
  fflush(stdout);
  ref--;
  if (ref < 0) fl_alert("My_Input %s deleted more than once: ref = 
%d",label(),ref);
  
  printf ("    box1.parent()  before remove: %p\n",box1.parent());
  if (box1.parent()) box1.parent()->remove(box1);
  printf ("    box1.parent()   after remove: %p\n",box1.parent());
  printf ("    box2->parent() before remove: %p\n",box2->parent());
  if (box2->parent()) box2->parent()->remove(box2);
  printf ("    box2->parent() after  remove: %p\n",box2->parent());
  printf ("    delete box2 ...\n");
  delete box2;
  printf ("    group %p has %d children\n",group,group->children());
  printf ("--- ~My_Input (%s): ref = %d, parent()=%p\n",label(),ref,parent());
  fflush(stdout);

}


void button1_cb(Fl_Widget *,void *) {
  printf (">>> button1_cb - group %p has %d 
children\n",group,group->children());
  fflush(stdout);
  button1->deactivate();
  printf ("    button1_cb - remove input1 ...\n");

  group->remove(input1); // ** remove from group !
  
  printf ("    button1_cb - group %p has %d 
children\n",group,group->children());
  printf ("    button1_cb - delete input1 ...\n");
  delete input1;
  printf ("--- button1_cb - group %p has %d 
children\n",group,group->children());
  fflush(stdout);
  window->redraw();
}

void button2_cb(Fl_Widget *,void *) {
  printf (">>> button2_cb - group %p has %d 
children\n",group,group->children());
  fflush(stdout);
  button1->deactivate();
  button2->deactivate();
  window->remove(group);
  printf ("--- button2_cb - group %p has %d 
children\n",group,group->children());
  fflush(stdout);
  printf ("    button2_cb - delete group ...\n");
  delete group;
  window->redraw();
}


int main(int argc, char **argv) {
  setvbuf (stdout,NULL,_IONBF,0);         // set stdout unbuffered
  window = new Fl_Window(600,400);
    group = new Fl_Group(10,10,580,180);
      input1 = new My_Input( 50,50,100,20,"1");
      input2 = new My_Input(350,50,100,20,"2");
    group->end();
    group->box(FL_FRAME_BOX);
    printf("Group %p has %d children\n",group,group->children());
    fflush(stdout);
    button1 = new Fl_Button( 50,250,200,100,"Delete Input 1");
    button1->callback(button1_cb,0);
    button2 = new Fl_Button(350,250,200,100,"Delete Group");
    button2->callback(button2_cb,0);
  window->end();
  printf("Group %p has %d children\n",group,group->children());
  fflush(stdout);
  window->show(argc, argv);
  return Fl::run();
}

/*
=============================================================

  running this program with ddd (gdb) under linux:

  # comments are added after "#"

(gdb) run
Group 0x8083090 has 6 children
Group 0x8083090 has 6 children

# click button 1: everything is okay ...

>>> button1_cb - group 0x8083090 has 6 children
    button1_cb - remove input1 ...
    button1_cb - group 0x8083090 has 5 children
    button1_cb - delete input1 ...

# start destructor Input 1
    
>>> ~My_Input (1): ref = 1, parent()=(nil)
    group 0x8083090 has 5 children
    box1.parent()  before remove: 0x8083090
    box1.parent()   after remove: (nil)
    box2->parent() before remove: 0x8083090
    box2->parent() after  remove: (nil)
    delete box2 ...

# start destructor Input 1, Box 2

>>> ~My_Box(1[2]): this=0xb741d008, ref=1, parent()=(nil)
    group 0x8083090 has 3 children
--- ~My_Box(1[2]): this=0xb741d008, ref=0, parent()=(nil)

# finished destructor Input 1, Box 2

    group 0x8083090 has 3 children
--- ~My_Input (1): ref = 0, parent()=(nil)

# finished destructor Input 1

# start destructor Input 1, Box 1 (automatic destructor)

>>> ~My_Box(1[1]): this=0xb781e080, ref=1, parent()=(nil)
    group 0x8083090 has 3 children
--- ~My_Box(1[1]): this=0xb781e080, ref=0, parent()=(nil)

# finished destructor Input 1, Box 1

--- button1_cb - group 0x8083090 has 3 children

# click button 2: this crashes ...

>>> button2_cb - group 0x8083090 has 3 children
--- button2_cb - group 0x8083090 has 3 children
    button2_cb - delete group ...

# start destructor Input 2
    
>>> ~My_Input (2): ref = 1, parent()=0x8083090
    group 0x8083090 has 0 children

# 0 children, because Fl_Group::clear() does: children_ = 0;

# try to remove box1 and box2 from their parent groups

    box1.parent()  before remove: 0x8083090
    box1.parent()   after remove: 0x8083090
    box2->parent() before remove: 0x8083090
    box2->parent() after  remove: 0x8083090

# both failed, because Fl_Group::clear() does: children_ = 0;

    delete box2 ...

# start destructor Input 2, Box 2

>>> ~My_Box(2[2]): this=0xb6c1b008, ref=1, parent()=0x8083090
    group 0x8083090 has 0 children
--- ~My_Box(2[2]): this=0xb6c1b008, ref=0, parent()=0x8083090

# finished destructor Input 2, Box 2
# parent() is still 0x8083090, but will be set to 0 in
#   Fl_Widget's destructor

    group 0x8083090 has 0 children
--- ~My_Input (2): ref = 0, parent()=0x8083090

# finished destructor Input 2


# start destructor Input 2, Box 1 (automatic destructor)

>>> ~My_Box(2[1]): this=0xb701c080, ref=1, parent()=0x8083090
    group 0x8083090 has 0 children
--- ~My_Box(2[1]): this=0xb701c080, ref=0, parent()=0x8083090

# finished destructor Input 2, Box 1

# now, Input 2 has been deleted, and its boxes have been deleted,
# too, but Fl_Group::clear tries to access box 1 and box 2 of
# Input 2, which have been deleted before !

# ... and here, it crashes ...

Program received signal SIGSEGV, Segmentation fault.
0x0804c130 in Fl_Widget::parent (this=0xb701c080) at Fl_Widget.H:107

# this=0xb701c080  ==  Box 1 of Input 2


(gdb) frame 0 # followed by "up" several times -> show stack frames:

#0  0x0804c130 in Fl_Widget::parent (this=0xb6f79080) at Fl_Widget.H:107
#1  0x080507df in Fl_Group::clear (this=0x8083090) at Fl_Group.cxx:357
#2  0x0805083f in ~Fl_Group (this=0x8083090) at Fl_Group.cxx:363
#3  0x0804bd69 in button2_cb () at crash_1.cxx:141
#4  0x0804e8ba in Fl_Widget::do_callback (this=0x8083178) at Fl_Widget.H:187
#5  0x0804eed5 in Fl_Button::handle (this=0x8083178, event=2) at 
Fl_Button.cxx:112
(gdb) 

(gdb) print o->parent_
Cannot access memory at address 0xb701c080      # box 1 of Input 2
(gdb) print o->parent()
Cannot access memory at address 0xb701c080      # box 1 of Input 2
(gdb) print o
$1 = (class Fl_Widget *) 0xb701c080
(gdb) 
(gdb) print i                           # scope: Fl_Group::clear()
$2 = 1

# this means, that Box 1 and Box 2 are still to be deleted.

==================================================================
*/
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs

Reply via email to