2013-02-02 5 views
0

Я пишу систему событий, где программист может создавать свои собственные события, но у меня проблема с указателями void для передачи данных о событиях. Система событий работает примерно так:Указатели 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);' как определяется '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' struct будет изменено «прямо из-под носа» первого обработчика события. Было бы лучше, если 'malloc()' новая структура каждый раз, когда вы запускаете событие, и 'free()' it в конце обработчика. – sheu

+0

@sheu, да, я думал об использовании этого, но в моем приложении это невозможно. – MiJyn

+0

никогда не говори никогда. Лучше быть в безопасности сейчас, а затем провести день спустя, отлаживая, почему ваши события не работают :-). Это хорошая привычка, и это не позволяет вам использовать глобальную переменную, что является еще одной привычкой избегать. – sheu

Смежные вопросы