47632

GTK+ g_pointer_connect passing data incorrectly

Question:

I have a problem with passing my data to the function when using g_signal_connect().

guint x = 777; gpointer ptr = &x; g_print(std::to_string(*(guint*)p).c_str()); g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), ptr);

The g_print in this piece of code outputs "777". However when the <em>funct</em> is called

static void funct(gpointer data) { g_print(std::to_string(*(guint*)data).c_str()); }

the g_prints outputs some garbage like: "81382720"

Can anyone help me with this?

Answer1:

You're passing a pointer to a local variable (x), and a local variable is allocated on the stack. To keep it alive outside of the scope of that function, allocate it on the heap instead (or optionally use a static or global variable).

guint *ptr = g_malloc(sizeof(guint)); *ptr = 777; g_print(std::to_string(*ptr).c_str()); g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), ptr);

Don't forget to call g_free to free that pointer when you don't need it anymore to avoid a memory leak.

<strong>EDIT:</strong>

I missed the fact that the signature of your callback is wrong as it doesn't respect the one of the destroy signal. This is a bug and must be fixed. Thanks to el.pescado for pointing that out.

Remarks on the other posts are valid too, but don't affect correctness:

<ul><li>GUINT_TO_POINTER/GPOINTER_TO_UINT can be used for that simple case to avoid dynamic allocation</li> <li>your call to g_print is unnecessary complicated</li> </ul>

Answer2:

First, signal handlers receive by default pointer to object that received signal as first argument, and user data as last argument. So, your signal handler should have the following <a href="https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget-destroy" rel="nofollow">signature</a>:

static void funct(GtkWidget *object, gpointer data) { /* ... */ }

Second, x is a local value, so it might (though not necessarily) be out of scope by the time callback is called. To fix it you could either extend its lifetime by allocating it on heap (g_new, new, malloc) or making it global/static. Alternatively, since an uint fits in pointer, you could use macros <a href="https://developer.gnome.org/glib/stable/glib-Type-Conversion-Macros.html#GUINT-TO-POINTER:CAPS" rel="nofollow">GUINT_TO_POINTER</a>/<a href="https://developer.gnome.org/glib/stable/glib-Type-Conversion-Macros.html#GPOINTER-TO-UINT:CAPS" rel="nofollow">GPOINTER_TO_UINT</a> to store/retrieve x directly in pointer.

Last, <a href="https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-print" rel="nofollow">g_print</a> function provides formatted output like printf - instead of creating temporary std::string and extracting char pointer form it:

g_print(std::to_string(*(guint*)p).c_str());

You could simply use %u format specifier to print guint:

g_print("%u", *p);

To sum up:

guint x = 777; g_print("%u", x); g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), GUINT_TO_POINTER(x)); // ... static void funct(GtkWidget *object, gpointer data) { g_print("%u", GPOINTER_TO_UINT(data)); }

Answer3:

I'm suspecting that variable x is already out of scope and destroyed when callback get called when the window's "destroy" signal get called. Thus the pointer is not valid anymore when it is dereferenced.

Answer4:

If you just want to store an integer value, use GINT_TO_POINTER() to store the value :

guint x = 777; g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), GINT_TO_POINTER(x));

and GPOINTER_TO_INT() to retrieve it:

static void funct(gpointer data) { guint x = GPOINTER_TO_INT(data); }

Recommend

  • g_signal_connect “pad-added” doesn't work
  • Wildfly JMS: MDB beans idle when messages exist
  • set a new context to WebView
  • Changing GtkButton color when GtkWindow is changed
  • kafka retention policy didn't work as expected
  • Is Python requests doing something wrong here, or is my POST request lacking something?
  • Detecting (on the server side) when a Flex client disconnects from BlazeDS destination
  • Debugging an ongoing .net process
  • Detecting modifications with an IEnumerable
  • Get the upload progress
  • What is the state of Java Beans Binding?
  • Tail recursion with tasks?
  • Symfony 3 new project error
  • staticfiles and STATIC_URL with virrtualenv - django
  • The required anti-forgery cookie “__RequestVerificationToken” is not present. MVC 5
  • cast stl::vector containing pointers to stl::vector containing constant pointers
  • What is a good persistence design for this entity hierarchy?
  • CHAR vs VARCHAR for password security
  • Waiting for $.post to finish
  • OSStatus error -50 (invalid parameters) AudioQueueNewInput recording audio on iOS
  • C++ stl pop doesn't return [closed]
  • How to remove last utf8 char of a python string
  • Unable to set a breakpoint on main while debugging a program compiled with Rust 1.10 with GDB
  • How to work with AMMediaType for video filters
  • Netlink sockets and libnl - nl_recvmsgs_default returning -16 (EBUSY)
  • How to unpack 32bit integer packed in a QByteArray?
  • allocating memory to an array of string
  • jQuery: add elements until a particular height is reached
  • DIV instruction jumping to random location?
  • print() is showing quotation marks in results
  • Is it possible to access block's scope in method?
  • why overloaded new operator is calling constructor even I am using malloc inside overloading functio
  • Why is the size of this struct 32?
  • JavaScriptCore crash on iOS9
  • Can I have the cursor start on a particular column by default in jqgrid's edit mode?
  • bootstrap to use multiple ng-app
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • Busy indicator not showing up in wpf window [duplicate]
  • Why do underscore prefixed variables exist?