2013-02-02 40 views
0

我正在編寫一個事件系統,程序員可以在其中創建自己的事件,但我遇到了用於傳遞事件數據的void指針的問題。事件系統的工作原理大致是這樣的:事件系統中的無效指針

typedef enum { ... USER_EVENT ...} event_type; 

typedef struct { 
    int id; 
    void* data; 
} user_event; 

typedef struct { 
    event_type type; 
    union { 
     ... 
     user_event user; 
     ... 
    }; 
} event; 

所以我在寫一個用戶事件,用我自己的自定義結構,並將它傳遞給這個函數:

void add_user_event(int id, void* data) { 
    event e; 
    user_event u; 
    u.id = id; 
    u.data = data; 
    e.type = USER_EVENT; 
    e.user = u; 
    add_event(e); /* add_event is just a function that adds the event to the event stack, and it works fine with predefined events */ 
} 
... 
add_user_event(my_user_event_id, (void*)&data); 

然後我找回它像這個:

... 
if (e.type == USER_EVENT && e.user.id == the_user_id) { 
    user_data_struct data = *(user_data_struct*) e.user.data; 
    /* do stuff */ 
} 

事情是,這應該工作,但它不(它只是給出了完全亂碼的數據)。我確信數據給出是可以的(做了一些檢查),但是它以某種方式沒有得到正確的數據(可能是一個錯誤的指針位置?)。其他一些提示(如果這可能有幫助的話)是add_user_event調用是在一個函數內進行的(並且該函數是在該函數內定義的)。這會影響到什麼嗎?

在此先感謝,並讓我知道如果這不夠清楚。

+0

在'add_user_event(my_user_event_id,(無效*)&data);'如何是數據定義的嗎?它可能是某個函數的局部對象嗎? – cnicutar

+0

@cnicutar,是的,「對象」是在一個函數中定義的,如果這就是你的意思 – MiJyn

+0

它是否能夠存活足夠長的時間來取消引用它? – cnicutar

回答

1

結果發現這個問題,正如cnicutar指出的,與void指針或任何東西都沒有關係,這只是因爲事件的數據存儲在函數中(事件處理函數在函數完成執行後調用,因此數據在甚至可以訪問之前就被銷燬了)。

所以這是我的原代碼:

void fire_my_event() { 
    my_event_structure ev; 
    /* do stuff with ev */ 
    add_user_event(my_event_id, (void*)&ev); 
} 
/* ev is now destroyed, before the event handler could be called */ 

我通過使ev 「全球性」,像這個固定:

my_event_structure ev; 

void fire_my_event() { 
    /* reset ev and set values */ 
    add_user_event(my_event_id, (void*)&ev); 
} 
/* ev will not be destroyed until the end of the program */ 
+0

這不是線程安全的,或者甚至是對多個事件的安全。如果在事件解決之前調用了兩次'fire_my_event',那麼'ev'結構的值將被改爲「從第一個事件處理程序的底層出發」。每次觸發一個事件時'malloc()'一個新的結構,並且在處理程序結束時釋放'free()'會更好。 – sheu

+0

@sheu,是的,我想過使用它,但在我的應用程序中,這是不可能發生的。 – MiJyn

+0

永不言敗。現在最好保證安全,然後花一天時間調試爲什麼你的事件不起作用:-)。這是一個很好的習慣,它可以避免使用全局變量,這是另一種避免的習慣。 – sheu