After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 651247 - Cannot get Goocanvas::Polyline constructor with Points argument to work.
Cannot get Goocanvas::Polyline constructor with Points argument to work.
Status: RESOLVED NOTABUG
Product: goocanvasmm
Classification: Other
Component: general
1.90.x
Other Linux
: Normal major
: ---
Assigned To: goocanvasmm-maint
goocanvasmm-maint
Depends on:
Blocks:
 
 
Reported: 2011-05-27 13:36 UTC by John
Modified: 2011-06-03 18:38 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case (2.12 KB, application/x-compressed-tar)
2011-06-02 04:37 UTC, John
Details
UI file for project (18.91 KB, text/plain)
2011-06-02 14:05 UTC, John
Details
config.h (2.34 KB, text/plain)
2011-06-02 14:06 UTC, John
Details

Description John 2011-05-27 13:36:32 UTC
I'm confused about the correct use of Polyline in Goocanvasmm 2.0. The
following

  points = new Goocanvas::Points(STRIP_MAX_LENGTH);
  line = Goocanvas::Polyline::create(false, *points);

gives a segmentation fault on the second line, complaining about the Polyline
operator= 

Points and line are declared as:

  Goocanvas::Points *points;
  Glib::RefPtr<Goocanvas::Polyline> line;

I cannot find any example for Goocanvasmm 2.0 Polylines with non-single-line
creation. A demo program available on the 'net comments out that mode and
instead instantiates all line segments line-by-line:

http://www.google.com/codesearch/p?hl=en#vaS0EaWX668/examples/demo/primitives.cc&q=Goocanvas::Polyline::create&d=2

which seems to indicate some problem with Polylines... 

Can anyone help me out here? Preferable with a pointer to a working 
example?
Comment 1 Kjell Ahlstedt 2011-05-30 09:07:44 UTC
The example code you link to is probably the demo example in goocanvasmm,
http://git.gnome.org/browse/goocanvasmm/tree/examples/demo

I uncommented this code in primitives.cc
/*
  Glib::RefPtr<Goocanvas::Points> points = Goocanvas::Points::create(4);
  points->set_coordinate(0, 340, 170);
  points->set_coordinate(1, 340, 230);
  points->set_coordinate(2, 390, 230);
  points->set_coordinate(3, 390, 170);
  line = Goocanvas::Polyline::create(false, points); 
        root->add_child(line);
*/

then changed it so it compiles

  Goocanvas::Points* points = new Goocanvas::Points(4);
  points->set_coordinate(0, 340, 170);
  points->set_coordinate(1, 340, 230);
  points->set_coordinate(2, 390, 230);
  points->set_coordinate(3, 390, 170);
  line = Goocanvas::Polyline::create(false, *points);
        root->add_child(line);

I can run the modified program without a segmentation fault. The extra
polyline is written.

I've used the latest source code from the Git repository for goocanvasmm,
goocanvas, gtkmm, etc.

Can you please supply a small test case that shows the bug you've found.
Or check if a suitably modified demo example crashes on the version of
goocanvasmm that you use.
Comment 2 John 2011-06-02 04:33:10 UTC
> then changed it so it compiles
> 
>   Goocanvas::Points* points = new Goocanvas::Points(4);
>   points->set_coordinate(0, 340, 170);
>   points->set_coordinate(1, 340, 230);
>   points->set_coordinate(2, 390, 230);
>   points->set_coordinate(3, 390, 170);
>   line = Goocanvas::Polyline::create(false, *points);
>         root->add_child(line);

Hello Kjell,

My apologies for the delay in responding.

I hadn't changed the demo to test it, but the code I used in my program
was very similar:

  channel[chan_nr].points = new Goocanvas::Points(STRIP_MAX_LENGTH);
  channel[chan_nr].line = Goocanvas::Polyline::create(false, *channel[chan_nr].points);

I get the segfault in the second line. The complete code is very short, so
I'll add it as an attachment.

John
Comment 3 John 2011-06-02 04:37:37 UTC
Created attachment 189058 [details]
Test case
Comment 4 Kjell Ahlstedt 2011-06-02 09:13:02 UTC
I can't run your test case without file src/ejemplo1.ui.
main.cc also includes config.h. Is that file also necessary, or can I just
remove '#include "config.h"'? The program compiles, if I do that.
Comment 5 Kjell Ahlstedt 2011-06-02 13:18:26 UTC
I still haven't been able to run your program up until the segmentation fault,
but I studied your code, and I think I know what's the problem.

You allocate memory with realloc(), which returns uninitialized memory.
  channel = (Channel *) realloc(channel, nr_channels * sizeof(Channel));

'channel' is a pointer to the struct
   typedef struct {
       double min, max, actual;
       Goocanvas::Points *points;
       Glib::RefPtr<Goocanvas::ItemSimple> line;
   } Channel;

When you allocate memory this way, the constructor of Channel::line is not
executed. Glib::RefPtr contains a pointer, which is not cleared. When you
assign to Channel::line, Glib::RefPtr tries to access the object pointed to by
the uninitialized pointer, if it's not 0.

You could save your program by clearing the newly allocated memory with
memset(), but it's a bad idea. You should allocate memory for C++ objects in
such a way that their constructors are executed.
Comment 6 John 2011-06-02 14:05:22 UTC
Created attachment 189083 [details]
UI file for project

Thanks for looking at the code! I'll add the config.h too, though it's probably not necessary for this simple case.

Yes, I read about the uninitialized memory from realloc. But isn't that the case for any C++ variable declaration? The demo example also declares 

Glib::RefPtr<Goocanvas::ItemSimple> line;

without assigning any value. I'm not entirely clear on the function of the RefPtr, but would this be the same case? According to http://www.intap.net/~drw/cpp/cpp03_02.htm:

"In some languages, variables are initialized to 0 - that is, a variable's initial value will be 0. This is not true of C++! "

I had already tried to use 'new' with the polyline, but the constructor is declared protected, so that doesn't work - create seems the only way.
Comment 7 John 2011-06-02 14:06:03 UTC
Created attachment 189084 [details]
config.h
Comment 8 Kjell Ahlstedt 2011-06-02 16:49:46 UTC
(In reply to comment #6)
> The demo example also declares 
> 
> Glib::RefPtr<Goocanvas::ItemSimple> line;
> 
> without assigning any value. I'm not entirely clear on the function of the
> RefPtr, but would this be the same case?

No, it's not the same case. When you declare 'line' like this as a local
variable on the stack, its default constructor is executed. Glib::RefPtr
contains the pointer

  T_CppObject* pCppObject_;

and its default constructor clears that pointer:

   template <class T_CppObject> inline
   RefPtr<T_CppObject>::RefPtr()
   :
     pCppObject_ (0)
   {}

realloc() is a C function. It knows nothing about C++ constructors.

> I had already tried to use 'new' with the polyline, but the constructor is
> declared protected, so that doesn't work - create seems the only way.

Yes, create() is only way, and the correct way. The error is that Channel::line
has not been correctly initialized when you assign to it. RefPtr's assignment
operator checks if it already points to another Goocanvas::ItemSimple, and if
it does, it unreferences that object. In your case, the pointer in RefPtr is
not null, but it does not contain a valid pointer.

I changed the declaration of StripPlot::channel to

    std::vector<Channel> channel;

and replaced

  channel = (Channel *) realloc(channel, nr_channels * sizeof(Channel));
by
  channel.push_back(Channel());

Then there is no segmentation fault.
There are of course other possibilities. The important thing is that you create
each new Channel object in such a way that its constructor is executed.
Comment 9 John 2011-06-03 14:58:46 UTC
Hello Kjell,

It seems I still have a long way to go with C++ programming (that's a
good thing - no boredom in sight).

Thanks for explaining this, and I think I'm starting to understand
the issue.

Is there any literature on the subject of RefPtrs, Proxies, and other
such exotic functions? I did quite a bit of searching, but didn't find
much except for the Doxygen-generated reference information, which
isn't exactly educational.

I do feel there is quite a learning curve to using the 'mm' libraries,
and somewhat above the knowledge level of average C++ programmers.

Thanks for your patience!

John
Comment 10 Kjell Ahlstedt 2011-06-03 18:22:16 UTC
(In reply to comment #9)
> Is there any literature on the subject of RefPtrs, Proxies, and other
> such exotic functions?

If you haven't read "Programming with gtkmm", you should read it. It's
available at http://developer.gnome.org/gtkmm-tutorial/. Appendix A discusses
RefPtr. Signal proxies are mentioned in Appendix B.

Hope you don't mind that I change this bug's resolution from FIXED to NOTABUG.
It's not a bug in goocanvasmm or glibmm or any other mm module.
Comment 11 John 2011-06-03 18:38:23 UTC
Thanks again, Kjell! I'll try to download that tutorial, but I must have had bad luck, because previous times (and now too), I couldn't get at it. The browser keeps staring at a blank page till it times out (Firefox 4.0)

> Hope you don't mind that I change this bug's resolution from FIXED to NOTABUG.
> It's not a bug in goocanvasmm or glibmm or any other mm module.

Of course I don't mind - I hadn't noticed that possibility.

Cheers,
John