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 744854 - OptionContext parse bug
OptionContext parse bug
Status: RESOLVED FIXED
Product: glibmm
Classification: Bindings
Component: object
2.42.x
Other Linux
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2015-02-20 13:26 UTC by Tom Schoonjans
Modified: 2015-02-25 09:43 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
C example: works as expected (1010 bytes, text/x-csrc)
2015-02-20 13:27 UTC, Tom Schoonjans
Details
C++ example: not working as expected... (1.25 KB, text/x-c++src)
2015-02-20 13:27 UTC, Tom Schoonjans
Details

Description Tom Schoonjans 2015-02-20 13:26:44 UTC
After some fooling around with glibmm's command-line option handling, I noticed that I got different results compared to (what I believe is) an analogue glib situation.


Basically I added a boolean type option 'feature' with two entries in the main group: '--enable-feature' and '--disable-feature'. Obviously depending on the initial value of the boolean variable, one of these options will correspond to the default behaviour.

This works fine in glib, but fails in glibmm. Interestingly, if I remove the default option, it works as expected.

I attached two files, one in C and one in C++ to demonstrate this problem.

I am using glib 2.42.1 and glibmm 2.40.0.
Comment 1 Tom Schoonjans 2015-02-20 13:27:22 UTC
Created attachment 297392 [details]
C example: works as expected
Comment 2 Tom Schoonjans 2015-02-20 13:27:55 UTC
Created attachment 297393 [details]
C++ example: not working as expected...
Comment 3 Kjell Ahlstedt 2015-02-22 15:37:58 UTC
Glib's g_option_context_parse() has access to pointers to the data in the
application program, in your C example gboolean feature1 and gboolean
feature2. It's no problem that two GOptionEntry elements contain pointers to
the same variable.

Glibmm's Glib::OptionGroup::add_entry() introduces an extra level of
indirection. Each call to add_entry() with a bool argument allocates a new
gboolean. A pointer to that gboolean is what is available to
g_option_context_parse() when it's called from Glib::OptionContext::parse().
When the program is called with a --disable-feature1 argument, only one of the
gbooleans corresponding to feature1 is set to false. Then both of them are
copied to feature1, and the result depends of which one is copied last.

There's another situation where this extra level of indirection gives
surprising results. If the default value is set after the call to add_entry(),
that assignment has no effect. Try

  bool feature2 = false;
  ................
  //option_group.add_entry(entry1a, feature1);
  option_group.add_entry(entry1b, feature1);
  option_group.add_entry(entry2a, feature2);
  //option_group.add_entry(entry2b, feature2);
  feature2 = true; // Added

and call the program with no arguments. feature2 == false!

At the moment I don't know how to fix it. We do need the extra level of
indirection in order to convert between C types and C++ types.
Comment 4 Tom Schoonjans 2015-02-23 09:39:22 UTC
Thanks for looking into this.

I have managed to circumvent this undesired behavior by removing the default options.

Would it be possible to fix this by not using the allocated gboolean in the G_OPTION_ARG_NONE case and just continue working with the initial bool instead? 
Or would it be too messy to remove the extra indirection in this particular case?
Comment 5 Kjell Ahlstedt 2015-02-25 09:33:59 UTC
It would be risky to let glib write directly to a bool variable, when it
believes it's writing to a gboolean variable. Can we be sure a bool variable
is identical to a gboolean? Regardless of which compiler has been used?

I've fixed the issue in another way. I found a reasonably easy way to allocate
just one common gboolean variable for several options that refer to the same
bool variable. I even made it work that way for options of other types as well:
If several options refer to the same C++ variable, they will all share the same
C variable when g_option_context_parse() is called. The only restriction is
that the test for same C++ variable only checks within one OptionGroup.
It won't work if two options in different option groups refer to the same C++
variable.

https://git.gnome.org/browse/glibmm/commit/?id=76c68945df98788984d1187c80a6f334391d090e
Comment 6 Tom Schoonjans 2015-02-25 09:43:36 UTC
You're right: though gboolean is typedef'ed to int (through gint), the size of bool is left up entirely by the C++ implementation.


Many thanks for fixing the bug with such an elegant solution!