【问题标题】:How to create wrappers to library functions with original name?如何为具有原始名称的库函数创建包装器?
【发布时间】:2019-10-15 13:43:07
【问题描述】:

我觉得这个问题很有趣:How to force compilation error if function return value is not checked?

如果您不检查返回值,则会强制执行编译错误。我为这个问题写了一个答案,你可以像这样使用 gcc 扩展:

__attribute__ ((warn_unused_result)) int foo (void) 
{
    return 5;
}

强制发出警告并使用-Werror=unused-result 进行编译,以使编译器在您不以某种方式使用返回值时生成错误。

现在我想为常规标准函数创建包装函数。一个想法是像这样重命名它们:

__attribute__ ((warn_unused_result)) realloc_wrapper(void *ptr, size_t new_size)
{
    return realloc(ptr, new_size);
}

但问题是这迫使我使用不同的名称,这会导致大量搜索和替换。当然,这可以自动完成,但仍然可以。最好,我希望能够创建一个我可以使用的头文件,而不是任何程序的标准 C 头文件。一个用例是调试一个大程序时。然后这会立即指出错误的潜在原因。

TL;DR

所以简而言之,我希望能够参加这个项目:

#include <stdlib.h>

int main(void)
{
    char *ptr;
    realloc(ptr, 42);
}

并将其更改为:

// Replaced stdlib with a custom header
#include <mystdlib.h>

int main(void)
{
    char *ptr;
    realloc(ptr, 42);
}

然后带有realloc 的行应该会生成一个警告。

我可以补充一点,我可以接受不是 100% 完美的解决方案。预期用途是用于调试而不是生产代码。

编辑:

我刚刚注意到realloc 是一个糟糕的选择,因为它似乎已经默认具有此声明,但我使用了 PSkocik 并使其适用于fgets

【问题讨论】:

    标签: c gcc return-value


    【解决方案1】:

    一个简单的解决方案是使用同名宏来隐藏函数。 (我将以puts 为例,因为正如您所提到的,realloc 通常已经用warn_unused_result 声明)

    /*begin your header:*/
    
    #include <stdio.h>
    
    __attribute ((__warn_unused_result__)) static inline
    int puts_wrapper(char const*X) 
    { 
       return (puts)(X); 
    }
    #define puts(X) puts_wrapper(X)
    
    /*end your header*/
    
    int main(void) { puts("hello, world"); }
    

    puts 周围的括号不是必需的,但如果您愿意,它们允许您将定义移动到 puts_wrapper 定义之前。)

    或者,您可以简单地重新声明函数并添加 warn_unused_result 属性(适用于 gcc 和 clang)。

    /*begin your header*/
    #include <stdio.h>
    __attribute ((__warn_unused_result__)) int puts(char const*);
    /*end your header*/ 
    
    int main(void) { puts("hello, world"); }
    

    【讨论】:

    • 如果 OP #include 的这个标题,那不也包括stdlib.h 吗?从而引发冲突? (即,#define reallocstdlib.h realloc 都将可见。
    • @ryyker 不,因为符号 realloc 从系统标头到遇到 #define 为止仍然具有其含义。此外,由于此文件首先执行#include &lt;stdlib.h&gt;,因此由于文件中的包含保护,该文件的任何后续包含都将是空操作。
    • 我意识到 realloc 的特定功能不需要此功能,但 fgets 工作正常。
    • @ryyker 什么冲突?宏将掩盖外部定义。如果宏定义之前包括stdlib.h,那么现在如果stdlibrealloc 定义为void *realloc(void *, size_t); 而不是void *(realloc)(void *, size_t)(它可能确实如此)可能会导致问题,但如果你在定义之前包含,应该没有问题。诚然,一些标准库标识符被允许为宏,现在重新定义这些标识符将是有问题的。就个人而言,我更喜欢具有不同名称的包装器,但由于 OP 不希望这样......
    • 在答案中包含 cmets 以澄清这一点可能是一个想法。
    猜你喜欢
    • 2021-08-20
    • 2016-06-16
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    相关资源
    最近更新 更多