I found this question very interesting: How to force compilation error if function return value is not checked?
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;
}
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);
}
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);
}
and change it to:
// Replaced stdlib with a custom header
#include <mystdlib.h>
int main(void)
{
char *ptr;
realloc(ptr, 42);
}
and then the line with realloc
should generate a warning.
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.
EDIT:
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
.
Wrapper functions can be used to make writing computer programs easier. An example of this is the MouseAdapter and similar classes in the Java AWT library. Wrapper functions are useful in the development of applications that use third-party library functions.
In the context of software engineering, a wrapper is defined as an entity that encapsulates and hides the underlying complexity of another entity by means of well-defined interfaces.
Encapsulation is the process of wrapping a piece of code in a function, allowing you to take advantage of all the things functions are good for.
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"); }
(The parentheses around puts
aren't necessary but they allow you to move the define before the puts_wrapper
definition if you wanted to.)
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"); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With