2012-02-26 5 views
0

私はパネル全体を作成するメソッドを作成しています。コンテンツを含むフォームに追加します。パネルはアレイに格納されます。コールバックが起動されたときにシグナルコールバックデータポインターがジャンク値を指しているのはなぜですか?

ここに基本的な考え方があります。

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

私がいる問題は、私はスケールを移動したときに私は渡している& vscale_idは、後のジャンクは(それの値が32000の周りにジャンク数である)になることです。

しかし、gtk_signal_connectは一度だけ呼び出されます。 これはおそらく、コールスタックと関係があると思います。そのメモリのビットはもはや予約されていません。

しかし私はこれと同じことを他のパネルで先にやっていますが、うまくいきます。 私が変えたこと - 物事をちょっとしたものにしようとしています。

以前のバージョン私はすべてのパネルとウィジェットを別々の配列に持っていました。 例えば、私はそれをやっているこのいずれか一方

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

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

V_Panel **vscale_struct; 

配列や構造体の中にパネルを置く悩まない - 私は理解するので、私は後でそれらにアクセスする必要はありませんか? (私はあなたがラベルをリサイクルしてパネル(hとvbox)を描くことができるので、同じです)。

また、興味深いヒント - 私はvalgrindを実行するとうまくいきます。 。?。プログラムがメモリだここ

すべてのヘルプ あなたはgtk_signal_connectを呼び出すときには、おそらく何が起こっているかを説明することができた場合は使用しています -

ここに私の実際のコードです:http://pastebin.com/MGfUihjM

関連する行は 45、145、274です、308,391

答えて

2

問題は、スタック上の変数のアドレス(この場合は関数のパラメータ)を取得することです。メモリ内のそのアドレスは、スタックフレームの一部であるため、期待している値を保持し続けることは確実ではありません

整数value_idをコールバックユーザーデータポインタにパックする正しい方法は、GINT_TO_POINTERを使用することです。 GPOINTER_TO_INTを使用してそれを逆にします。

だからあなたの信号接続は次のようになります。

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

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

そして、あなたのシグナルハンドラには次のようになります。

関連する問題