2012-02-26 1 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와 vboxes)을 그림으로 만들 수 있다는 것을 알았습니다.

또한 흥미로운 단서 - 제가 valgrind를 실행하면 잘 작동합니다. 어떤 방법으로 valgrind가 프로그램은 메모리의 사용

어떤 도움을 여기 당신은 아마 당신이 gtk_signal_connect를 호출 할 때 무슨 일이 일어나고 있는지 설명 할 수있는 경우 -

가 여기 내 실제 코드의

:.?. http://pastebin.com/MGfUihjM

관련 라인 45, 145, 274입니다 , 308, 391

답변

2

문제는 스택의 변수 주소 (이 경우 함수의 매개 변수)를 취하는 것입니다. 메모리에있는 해당 주소는 스택 프레임의 일부일 뿐이므로 계속 기대하는 값을 유지할 수 있습니다.

정수 value_id을 콜백 userdata 포인터로 묶는 올바른 방법은 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; 
}