2013-04-18 4 views
2

У меня есть функциямакрос, чтобы проверить возвращаемое значение функции проверяется

void *custom_get_value(ObjectPtr) 

Эта функция традиционно никогда не используется для возвращения NULL.It может возвращать одно из следующих значений

uint32_t 
int32_t 
uint64_t 
int64_t 
uint8_t 

Поскольку функция не используется для возврата NULL у меня есть много кода, который делает

 *(uint32_t*)custom_get_value(ObjectPtr) 

        OR 

     *(uint64_t*)custom_get_value(ObjectPtr) 

Недавно ш е решили изменить поведение

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. 

Могу ли я использовать некоторый макрос idendify всех мест в коде, где возвращаемое значение

void *custom_get_value(ObjectPtr) 

не будучи checked.If да как я могу сделай это?

ответ

2

Вы не можете легко написать макрос, который может отслеживать, что происходит со значением после его возврата, поскольку анализ потока данных несколько превосходит возможности препроцессора. Однако, есть полезный метод разработан, чтобы помочь в ситуациях, таких как это, что это определить функцию, которую вы хотите проверить, как самосправочные макро:

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

Этот пример ничего не делает сам по себе, но он демонстрирует что-то полезное: когда имя макроса появляется как часть своего собственного списка заметок, вложенное вхождение имени «окрашивается в синий цвет» и не будет расширяться во второй раз. Таким образом, определяя существующее имя функции как макроса, вы можете «обернуть» (или «посоветовать») все существующие вызовы функции, предположительно разбросанные по вашему коду в неизвестном количестве мест, - с дополнительными действиями, в дополнение к сохранению оригинальное обращение.

Тогда у вас есть несколько вариантов, например:

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

... если вы на GCC или Clang, следует перечислить файл и номер строки каждой точке, где custom_get_value называется, во время компиляции , (Оба #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; 
} 

... который отвезет вас орехи печати сообщения каждый раз, когда функция вызывается, но, по крайней мере стандарт.

Вы можете даже обернуть все вызовы функцией, которая гарантирует, что результирующий указатель гарантированно будет ненулевым, хотя это, вероятно, не лучший способ справиться с этой ситуацией.

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,........) 
    // .... 
} 

Тогда вы можете иметь определенную обработку для того, когда каждое значения получает нулевой указатель возвращается.

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