dwjohnston
dwjohnston

Reputation: 11890

Why is the signal callback data pointer pointing to a junk value when the callback is fired?

Ok, I'm writing a method that creates an entire panel and it's containing contents and adds it to the form. The panels are stored in an array.

Here's the basic idea.

void vscale1Event(GtkWidget *widget, int *vscale_id)
{
    int value = gtk_range_get_value(GTK_RANGE(vscale_struct[*vscale_id]->vscale1)); 
    do stuff with this value; 
}


void add_vscale_panel(int vscale_id)
{
    vscale_struct[vscale_id]->vscale1 = ..... ;
    vscale_struct[vscale_id]->vscale2 = ..... ;
    add buttons to form; 

    gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]), "value_changed", (GtkSignalFunc)vscale1Event, &vscale_id); 
    gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]), "value_changed", (GtkSignalFunc)vscale2Event, &vscale_id);
}

int main()
{
    for (i = 0; i<n; i++)
    {
        add_vscale_panel(i); 
    }
}

The problem I'm having, is that &vscale_id that I'm passing in, later becomes junk (it's value is a junk number around 32000) when I move the scale.

But - the gtk_signal_connect is only being called that once. Ok, I get that it's probably something to do with the call stack, that bit of memory no longer being reserved.

But I did this same thing earlier for another panel, and it's working fine. what I've changed - is trying to make things a bit tidier.

The previous version I had all the panels and widgets each in seperate arrays. eg

GtkWidget **outerPanel;
GtkWidget **innerPanel1; 
GtkWidget **vscale1; 

whereas this one I'm doing it:

typedef struct 
{
    GtkWidget **vscale1;
    Gtkwidget **vscale2; 
} V_Panel;

V_Panel **vscale_struct; 

Not bothering putting the panels into arrays or structs - because I figure I don't need to access them later? ( I found that you can 'recycle' labels so I figure panels (h and vboxes), are the same.

Also - an interesting clue - when I run valgrind - it works fine. Some how valgrind changes the way the program uses it's memory.

Any help here? If you can perhaps explain what's happening when you call gtk_signal_connect. -

Here's my actual code: http://pastebin.com/MGfUihjM

relevant lines are 45, 145, 274, 308, 391

Upvotes: 0

Views: 69

Answers (1)

Rob Bradford
Rob Bradford

Reputation: 1460

The problem is that your taking the address of a variable on the stack - in this case the parameter to the function. That address in memory is definitely not guaranteed to continue to hold the value you expect it to since it is just part of the stack frame

The correct way to pack your integer value_id into the callback userdata pointer is to use GINT_TO_POINTER and to reverse it using GPOINTER_TO_INT.

So your signal connection would be:

gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]),
                   "value_changed",
                   (GtkSignalFunc)vscale1Event,
                   GINT_TO_POINTER(value_id)); 

And in your signal handler would look like:

void vscale1Event(GtkWidget *widget, gpointer userdata)
{
    int vscale_id = GPOINTER_TO_INT (userdata);
    int value = gtk_range_get_value(GTK_RANGE(vscale_struct[vscale_id]->vscale1)); 
    do stuff with this value; 
}

Upvotes: 2

Related Questions