为什么在回调被触发时,信号回调数据指针指向垃圾值?

时间:2012-02-26 02:53:15

标签: event-handling gtk valgrind

好的,我正在编写一个创建整个面板的方法,它包含内容并将其添加到表单中。面板存储在一个阵列中。

这是基本想法。

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); 
    }
}

我所遇到的问题是,当我移动比例时,我传入的&amp; vscale_id,后来变成了垃圾(它的值是一个大约32000的垃圾数字)。

但是 - gtk_signal_connect只被调用一次。 好吧,我知道它可能与调用堆栈有关,那个内存不再被保留。

但我之前为另一个小组做了同样的事情,并且它工作正常。 我改变了什么 - 试图让事情变得更加整洁。

之前的版本我将所有面板和小部件分别放在单独的数组中。 例如

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

而我正在做这件事:

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

V_Panel **vscale_struct; 

不打扰将面板放入阵列或结构中 - 因为我想我以后不需要访问它们? (我发现你可以回收&#39;标签,所以我计算面板(h和vbox),是相同的。

另外 - 一个有趣的线索 - 当我运行valgrind时 - 它工作正常。 valgrind如何改变程序使用它的记忆方式。

这里有什么帮助吗? 如果您可以解释在调用gtk_signal_connect时发生的事情。 -

这是我的实际代码:http://pastebin.com/MGfUihjM

相关的是 45,145,274,308,391

1 个答案:

答案 0 :(得分:2)

问题是你在堆栈上取一个变量的地址 - 在这种情况下是函数的参数。内存中的地址绝对不能保证继续保持您期望的值,因为它只是堆栈帧的一部分

将整数value_id打包到回调用户数据指针中的正确方法是使用GINT_TO_POINTER并使用GPOINTER_TO_INT将其反转。

所以你的信号连接是:

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

在您的信号处理程序中看起来像:

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; 
}