如何使用原始名称为库函数创建包装器?

klu*_*utt 6 c gcc return-value

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

如果您不检查返回值,将强制执行编译错误。我为该问题写了一个答案,您可以在其中使用gcc扩展,如下所示:

__attribute__ ((warn_unused_result)) int foo (void) 
{
    return 5;
}
Run Code Online (Sandbox Code Playgroud)

-Werror=unused-result如果您不使用返回值,则执行警告并进行编译以使编译器生成错误。

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

__attribute__ ((warn_unused_result)) realloc_wrapper(void *ptr, size_t new_size)
{
    return realloc(ptr, new_size);
}
Run Code Online (Sandbox Code Playgroud)

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

TL; DR

简而言之,我希望能够采用此程序:

#include <stdlib.h>

int main(void)
{
    char *ptr;
    realloc(ptr, 42);
}
Run Code Online (Sandbox Code Playgroud)

并将其更改为:

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

int main(void)
{
    char *ptr;
    realloc(ptr, 42);
}
Run Code Online (Sandbox Code Playgroud)

然后与的行realloc应生成警告。

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

编辑:

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

PSk*_*cik 5

一个简单的解决方案是用一个同名的宏来隐藏函数。(我将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"); }
Run Code Online (Sandbox Code Playgroud)

(圆括号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"); }
Run Code Online (Sandbox Code Playgroud)

  • @ryyker不行,因为符号`realloc`从系统头开始一直具有其含义,直到遇到`#define`为止。另外,由于此文件首先执行#include &lt;stdlib.h&gt;,因此,由于文件中的包含保护,此文件的任何后续包含都将变为无操作。 (2认同)