2013-02-02 2 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

) &data);'방법

그래서이 내 원래의 코드이었다 'data'가 정의 되었습니까? 어떤 함수의 로컬 객체 일 수 있습니까? – cnicutar

+0

@cnicutar, 예, 함수 내에서 "객체"가 정의되어있는 경우 그 객체가 의미하는 것이면 – MiJyn

+0

그리고 그것을 역 참조하기까지 충분히 오래 살아남습니까? ? – cnicutar

답변

1

cnicutar이 지적했듯이이 문제는 불규칙 포인터 또는 다른 것과 관련이 없었습니다. 단순히 이벤트 데이터가 함수 내에 저장 되었기 때문에 (이벤트 처리기가 함수 실행이 완료된 후에 호출 되었기 때문에, 따라서 데이터가 액세스되기도 전에 데이터가 파괴되었습니다).

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_user_event_id, (무효 * (add_user_event`에서

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

이것은 threadsafe가 아니며 여러 이벤트에 대해 안전하지도 않다. 이벤트가 해결되기 전에'fire_my_event'가 두 번 호출되면,'ev' 구조체의 값이 첫 번째 이벤트 핸들러의 "코앞에서 바르게"변경됩니다. 이벤트를 발생시킬 때마다 새로운 구조체를 malloc()하는 것이 좋을 것이다. 그리고 핸들러의 끝에서 그것을 free()한다. – sheu

+0

@sheu, 예, 사용하는 것에 대해 생각했지만 응용 프로그램에서는 이런 일이 일어날 수 없습니다. – MiJyn

+0

결코 절대로 말하지 마십시오. 지금은 안전 해지기를 바란다. 그런 다음 이벤트가 왜 작동하지 않는지 디버깅하는 데 하루를 보내야한다. 그것은 좋은 습관이고, 피할 또 다른 습관 인 전역 변수를 사용하지 못하도록합니다. – sheu

관련 문제