Wednesday, June 18, 2008

*Yet Another gcc optimization*

Have a look at these codes.

1)
/*example1.c*/
#include
int main()
{
char *p=NULL;
printf("%s\n", p);
return 0;
}
Output is,

Segmentation fault

2) Then I slightly changed the code,
/*example2.c*/
#include
int main()
{
char *p=NULL;
printf("%s \n", p); //add a space
return 0;
}

Now, output is

(null)


Why??
Mostly we assume that our GCC compiled source code is always calling the functions we wrote in the source code. Wrong!!!

Case 1)
>gcc example1.c
>nm --undefined-only a.out
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.0
U puts@@GLIBC_2.0

>

Case 2)

>gcc example2.c
>nm --undefined-only a.out
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.0
U printf@@GLIBC_2.0

>

So in first case, it is calling puts which gives segmentation fault and in second case printf is called which prints “(null)” in case of NULL pointer.

The optimization is that “A printf call with a simple format string ending with '\n' is converted to a puts() call.” So in first case its converted into puts call but in second case it remains as printf.

To get the original printf call with GCC-4.0.2 you must provide -fno-builtin or
-fno-builtin-printf as command line argument

>gcc example1.c -fno-builtin -fno-builtin-printf
>nm --undefined-only a.out
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.0
U printf@@GLIBC_2.0
>


Happy???