如何创建具有原始名称的库函数包装器?

如何创建具有原始名称的库函数包装器?

问题描述:

我发现这个问题非常有趣:如果未检查函数返回值,如何强制编译错误?

I found this question very interesting: How to force compilation error if function return value is not checked?

这是关于如果不检查返回值则强制执行编译错误.我写了这个问题的答案,您可以在其中使用gcc扩展名:

It's about enforcing compilation errors if you do not check the return value. I wrote an answer to that question where you can use gcc extensions like this:

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

强制执行警告,并使用-Werror=unused-result进行编译,如果您不以某种方式使用返回值,则会使编译器生成错误.

to enforce a warning and the compile with -Werror=unused-result to make the compiler generate an error if you don't use the return value somehow.

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

Now I would like to create wrapper functions to the regular standard functions. An idea is to rename them like this:

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

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

But the problem is that this forces me to use a different name, which would cause a lot of search and replace. Granted, this can be done automatically, but still. Preferably, I would like to be able to create a header that I can use instead of a standard C header for any program. One use case is when debugging a big program. Then this would instantly point me to potential causes of bugs.

因此,简而言之,我希望能够参加此计划:

So in short, I want to be able to take this program:

#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的行将生成警告.

and then the line with realloc should generate a warning.

我可能会补充说,我认为解决方案并非100%完美.预期用途是用于调试,而不是生产代码.

I might add that I'm ok with a solution that isn't 100% perfect. The intended use is for debugging and not production code.

我只是注意到realloc是一个错误的选择,因为默认情况下它似乎已经具有此声明,但是我使用了PSkocik并使它适用于fgets.

I just noticed that realloc was a bad choice, since it seems to already have this declaration by default, but I used PSkocik and made it work for fgets.

一个简单的解决方案是用一个具有相同名称的宏对函数进行屏蔽. (我将使用puts作为示例,因为正如您已经提到的,realloc通常已经用warn_unused_result声明了)

A straightforward solution would be to shadow the function with an identically named macro. (I'll use puts as an example, because, as you've mentioned, realloc is already usually declared with 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定义之前.)

(The parentheses around puts aren't necessary but they allow you to move the define before the puts_wrapper definition if you wanted to.)

或者,您可以简单地在添加了warn_unused_result属性的情况下重新声明该函数(适用于gcc和clang).

Alternatively, you could simply redeclare the function with the warn_unused_result attribute added (works on both gcc and clang).

/*begin your header*/
#include <stdio.h>
__attribute ((__warn_unused_result__)) int puts(char const*);
/*end your header*/ 

int main(void) { puts("hello, world"); }