【问题标题】:macro to check if the return value of a function is being checked用于检查是否正在检查函数的返回值的宏
【发布时间】:2013-04-11 01:57:24
【问题描述】:

我有一个功能

void *custom_get_value(ObjectPtr) 

此函数传统上从不用于返回 NULL。它可以返回以下任何值

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.

我可以使用一些宏来识别代码中所有返回值的地方

void *custom_get_value(ObjectPtr)

没有被检查。如果是,我该怎么做?

【问题讨论】:

    标签: c function macros void-pointers c-preprocessor


    【解决方案1】:

    将新函数命名为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,你只需要fox这个包装器。

    更简洁的方法是拥有一个获取您感兴趣的项目的功能:

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

    然后您可以对每个值何时返回空指针进行特定处理。

    【讨论】:

      【解决方案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;
      }
      

      ...每次调用函数时都会让您发疯,但至少是标准的。

      您甚至可以使用一个函数来包装所有调用,该函数将结果指针再次保证为非空,尽管这可能不是处理这种情况的最佳方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-16
        • 2021-10-01
        • 1970-01-01
        • 2012-08-19
        • 2020-10-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多