extern "C" int fprintf (FILE *__restrict __stream,
__const char *__restrict __format, ...)
{
va_list args;
int return_status = 0;
va_start(args,__format);
if (is_gui && (__stream == stdout || __stream == stderr)) {
return_status = showMessageInGui(NULL, __format, args);
}
else {
return_status = vfprintf(__stream, __format, args);
}
va_end(args);
return return_status;
}
Which only worked part of the time. Complicating matters was the behavior was different across multiple compiler versions: gcc4.2.4 exhibited the problem while gcc3.4.2 did not.
I did some digging around and found out that the newer version of gcc was actually implementing a level of optimization that undermined the approach of redefining printf. Basically, any argument to printf that did not contain a format string (%) to be filled in resulted in a translation by later versions of gcc to a call to fwrite (or puts). For example:
#include <stdio.h>
int main () {
printf ("With args %d\n", 10);
printf ("Without\n");
return 0;
}
Translates to
.LC0:
.string "With args %d\n"
.LC1:
.string "Without"
.text
...
movl $.LC0, %edi
movl $0, %eax
call printf
movl $.LC1, %edi
call puts
movl $0, %eax
Notice the puts call for the second call to printf. So regardless of what definition was provided for printf the code would never be executed. Try it with the following:
#include <stdio.h>
int printf (const char * fmt, ...) { return 1/0; }
int main () {
printf ("w00t\n");
return 0;
}
You'll see that a warning is presented (for division by zero) but the code runs without issue.
There were several solutions presented in the thread but the OP eventually chose to use gcc flags to prevent this behavior. Using -fno-builtin-fprintf and -fno-builtin-printf allowed compilation without the translation and the redefinition of printf worked as expected.
No comments :
Post a Comment