2013-04-18 2 views
2

내가이 기능은 전통적으로 다음 값을 반환 할 수 NULL.It을 반환하는 데 사용하지는 함수의 반환 값이

void *custom_get_value(ObjectPtr) 

기능이 확인되는 경우 확인

uint32_t 
int32_t 
uint64_t 
int64_t 
uint8_t 
함수가 NULL을 반환하는 데 사용되지 않습니다 때문에

나는 최근 w

 *(uint32_t*)custom_get_value(ObjectPtr) 

        OR 

     *(uint64_t*)custom_get_value(ObjectPtr) 

을 수행하는 코드를 많이 가지고 전자는

void *custom_get_value(ObjectPtr) 

의 반환 값이 checked.If되는하지 않는 코드에있는 모든 장소 예 내가 어떻게 할을 idendify하는

void *custom_get_value(ObjectPtr) in such a way that it can return NULL.So all occourances of the above scenario (de-referencing to specific types without checking the return value) can result in segmentation fault. 

내가 몇 가지 매크로를 사용할 수

의 동작을 수정하기로 결정했습니다 그렇게?

답변

2

데이터 흐름 분석이 전 처리기 기능을 약간 벗어나기 때문에 반환 된 값을 추적 할 수있는 매크로를 쉽게 작성할 수 없습니다. 그러나, 당신은 자기 참조 매크로로 검사 할 기능을 정의하는 것입니다 이와 같은 상황을 돕기 위해 설계된 유용한 기술이있다 :

#define custom_get_value(...) (0, custom_get_value(__VA_ARGS__)) 

이 예제는 그 자체로 아무것도하지 않습니다가, 매크로 이름이 자체 교체 목록의 일부로 나타나는 경우 이름의 중첩 된 항목은 "파란색으로 페인트 됨"이며 두 번째로 확장되지 않습니다. 따라서 기존 함수 이름을 매크로로 정의하면 함수의 기존 호출을 알 수없는 수의 코드에 흩어져 "추가"할 수 있습니다 (또는 "조언"). 원래 호출. 당신이 GCC 또는 연타에 있다면,라고 custom_get_value 모든 지점의 파일과 줄 번호를 나열 컴파일 시간에해야 ...

#define custom_get_value(...) ({ \ 
    _Pragma("message \"custom_get_value called\""); \ 
    custom_get_value(__VA_ARGS__); \ 
}) 

:

은 그럼 당신은 예를 들어, 몇 가지 옵션이 있습니다 . (#pragma message과 명령문 표현식 형식 모두 비표준 GCC 확장 기능입니다. 그러나 오래된 호출을 정리할 때만이 코드를 사용한다면 문제가되지 않을 수도 있습니다. 모든 호출이 검사되면 비표준 코드를 제거 할 수 있습니다.)

또는 대신 런타임 메시지를 적용하는 메시지를 함수가 호출 될 때마다 인쇄 견과류를 운전하지만, 적어도 표준합니다

#define custom_get_value(...) \ 
    custom_wrap(custom_get_value(__VA_ARGS__), __FILE__, __LINE__) 

void * custom_wrap(void * val, char * f, int l) { 
    printf("custom_get_value called in %s on line %d\n", f, l); return val; 
} 

....

이 상황을 처리하는 최선의 방법은 아니지만 결과 포인터를 다시 null이 아닌 것으로 보장하는 함수로 모든 호출을 래핑 할 수도 있습니다.

0

새 기능의 이름을 custom_get_value_ex으로 지정하고 이전 기능을 삭제하십시오. 그렇다면 컴파일러는 이전 함수의 모든 용도를 매우 친절하게 나타낼 것이므로 검토 할 수 있습니다.

일반적으로 이미 사용중인 함수의 의미를 변경하면 함수에 대한 모든 호출을 검토하는 것이 좋습니다.

아마도 이러한 호출 중 일부를 더 유지하기 쉬운 래퍼로 래핑 할 수 있습니다.

inline uint32_t custom_get_uint32(.....) 
{ 
    void *value = custom_get_value(.....); 
    if (!value) 
      return 0; // or some other error handling 
    return *(uint32_t *)value; 
} 

그런 다음 custom_get_value을 다시 변경하면이 래퍼 만 사용할 수 있습니다.

에도 정돈 당신이 관심있는 항목을 가져 오기위한 기능을하는 것입니다 :

inline uint32_t get_propeller_setting(.....) 
{ 
    void *value = custom_get_value(PROPELLER_SETTING,........) 
    // .... 
} 

그런 다음 각 값이 널 포인터가 돌아 오면 특정 처리를 할 수 있습니다.