Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

Become a GCC expert with these little-known command-line options

  
  
  

The GNU Compiler Collection (GCC) is easy to use, but it offers so many command-line options that no one can remember them all. Here are five uncommon command-line options you can use to get the most out of GCC.

To illustrate these examples, I used GCC 4.7.3 running on Ubuntu Linux 13.04 with Bash 4.2.45.

-save-temps

In simplest terms, the GCC compilation process internally follows four stages:

  • In the first stage, the preprocessor expands all the macros and header files, and strips off comments.
  • In the second stage, the compiler acts on the preprocessed code to produce assembly instructions.
  • In the third stage, the assembler converts the assembly instructions into machine-level code (object files).
  • In the final stage, the linker resolves all the unresolved symbols and combines all the object files to produce an executable.

When you compile a C/C++ source file using gcc, your final output is an executable program. But in some situations you might want to know how the preprocessor expanded a particular macro, or you might just want to take a look at the assembly instructions. To see the intermediate output produced after each of the compilation stages, use the -save-temps option.

For instance, suppose you compile the program helloworld.c using the -save-temps option:

$ gcc -Wall -save-temps helloworld.c -o helloworld

Along with the final executable, gcc produces three other files. helloworld.i is the output of the preprocessing stage, helloworld.s is the output of the compilation stage, and helloworld.o is the output of the assembly stage.

-Wextra

Many developers use the option -Wall to enable warnings during the compilation process, but -Wall does not report all possible warnings. It leaves out, for example, warnings about:

  • Missing parameter type
  • Comparison of a pointer with integer zero using >, <, >=, or <=.
  • Ambiguous virtual bases

If the compiler does not warn you about these problems, your program might produce undesired results when you run it. Consider the following code:

#include<stdio.h>

void func(a)
{
    printf("\n func() is passed parameter [%d]\n",a);
    return;
}

int main(void)
{
    printf("\n HELLO \n");
    func(0xFFFFF);
 
    return 0;
}

As you can see, the type of the argument "a" is not specified in function func(). This could be a typo on the part of the programmer who, for example, meant to declare "a" as a "long long" integer, but without that declaration the compiler will assume the default type of variable "a" as int. If you compile this code with the -Wall option, gcc does not produce any warning, and the program could produce undesired results. For example, if a "long long" value that is larger than the maximum value that an "int" can hold is passed as an argument to func(), the program will behave incorrectly.

If you compile the same code with the -Wextra option enabled, you should see the following output:

$ gcc -Wall -Wextra helloworld.c -o helloworld
helloworld.c: In function 'func':
helloworld.c:4:6: warning: type of 'a' defaults to 'int' [-Wmissing-parameter-type]

Once you know about this problem, you can easily fix it by explicitly mentioning the type of function argument "a."

-Wextra offers similar warnings for pointer comparison problems. Consider the following code:

#include<stdio.h>

void func()
{
    int a = -1;
    int *ptr = &a;

    if(ptr >= 0)
    {
        a = a+1;
    }
    printf("\n a = [%d]\n",a);
    return;
}

int main(void)
{
    printf("\n HELLO \n");
    func();

    return 0;
}

The pointer "ptr" is being compared with the integer zero in the function func(). This statement is useless, as ptr clearly contains the address of the variable "a," which will always be a positive value. The programmer must have missed the dereference operator * before ptr while comparing its value with zero. Just as in the previous example, if you compile this code with the -Wall option, gcc does not produce any warning, but the program will produce wrong result (a=0) in the output. On the other hand, when you use -Wextra, gcc reports:

$ gcc -Wall -Wextra helloworld.c -o helloworld
helloworld.c: In function 'func':
helloworld.c:9:12: warning: ordered comparison of pointer with integer zero [-Wextra]

As soon as you see a warning related to pointer comparison with zero, you immediately know you have a typo in your code, which you can easily fix by replacing (ptr>=0) with ((*ptr)>=0) in this case.

Read the gcc man page for other warnings -Wextra produces.

-Wfloat-equal

New programmers sometimes try to compare floating point variables using the == operator – something you should never do because of the way floating point numbers are represented internally. The gcc compiler's -Wfloat-equal option produces a warning whenever it encounters a floating point comparison. Consider:

#include<stdio.h>

void func(float a, float b)
{
    printf("\n Inside func() \n");
    if(a == b)
    {
        printf("\n a == b\n");
    }
    return;
}


int main(void)
{
    printf("\n HELLO \n");
    func(1.345, 1.345678);

    return 0;
}

Here, the float arguments to the function func() are being compared using the == operator. When you compile this code without using the -Wfloat-equal option, you'll see no warning, but with it, you should see output like this:

$ gcc -Wfloat-equal helloworld.c -o helloworld
helloworld.c: In function 'func':
helloworld.c:7:10: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]

If you see that your code is directly comparing floats, you should drop the direct comparison and think of better logic to solve the problem.

-g

If you use the GNU debugger (GDB) to debug, or Valgrind to detect memory leaks in your program, always compile the program with the -g option, which produces debugging information in the operating system's native format. Other tools can use this information to produce detailed output.

To see how it works, suppose the source file helloworld.c contains following code:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

void func()
{
    char *p = (char*) malloc(10);
    printf("\n Inside func() \n");
    return;
}

int main(void)
{
    printf("\n HELLO \n");
    func();

    return 0;
}

If you compile the code without the -g option and run Valgrind's memcheck tool, you'll see a problem – a memory leak:

$ valgrind --tool=memcheck --leak-check=yes ./helloworld
==3471== Memcheck, a memory error detector
==3471== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==3471== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3471== Command: ./helloworld
==3471==

 HELLO

 Inside func()
==3471==
==3471== HEAP SUMMARY:
==3471==     in use at exit: 10 bytes in 1 blocks
==3471==   total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==3471==
==3471== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3471==    at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3471==    by 0x40058D: func (in /home/himanshu/practice/helloworld_dir/helloworld)
==3471==    by 0x4005B6: main (in /home/himanshu/practice/helloworld_dir/helloworld)
==3471==
==3471== LEAK SUMMARY:
==3471==    definitely lost: 10 bytes in 1 blocks
==3471==    indirectly lost: 0 bytes in 0 blocks
==3471==      possibly lost: 0 bytes in 0 blocks
==3471==    still reachable: 0 bytes in 0 blocks
==3471==         suppressed: 0 bytes in 0 blocks
==3471==
==3471== For counts of detected and suppressed errors, rerun with: -v
==3471== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)

The memcheck tool is able to detect the memory leak, but it is unable to say where the leak actually takes place. Without that information, you could have a big problem tracking down the leak when you're working on projects that contain large source files.

If instead you compile the code with the -g option before you run memcheck, the tool can pinpoint the problem:

$ valgrind --tool=memcheck --leak-check=yes ./helloworld
==3517== Memcheck, a memory error detector
==3517== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==3517== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3517== Command: ./helloworld
==3517==

 HELLO

 Inside func()
==3517==
==3517== HEAP SUMMARY:
==3517==     in use at exit: 10 bytes in 1 blocks
==3517==   total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==3517==
==3517== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3517==    at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3517==    by 0x40058D: func (helloworld.c:7)
==3517==    by 0x4005B6: main (helloworld.c:16)
==3517==
==3517== LEAK SUMMARY:
==3517==    definitely lost: 10 bytes in 1 blocks
==3517==    indirectly lost: 0 bytes in 0 blocks
==3517==      possibly lost: 0 bytes in 0 blocks
==3517==    still reachable: 0 bytes in 0 blocks
==3517==         suppressed: 0 bytes in 0 blocks
==3517==
==3517== For counts of detected and suppressed errors, rerun with: -v
==3517== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)

You might also want to profile your program. Code profiling can tell you things such as how much time each function consumes, how many times a function gets called, and which parts of your program are slow and need improvement. In Linux, a popular code profiling tools is the GNU profiler, or gprof. This tool requires the code to be compiled (and linked) using gcc's -pg option. GNU gprof produces detailed profiling information in form of flat profile and call graph.

@file

All of these options may be useful, and you may want to use some or all of them together for all of your compiles. If you find yourself using many command-line options while compiling your programs, you can put all the options in a file and pass the file name to gcc to use all the flags in the file together. For instance, you could create a file named options that contains the line -Wall -Wextra -Wfloat-equal, then pass the file name as a command-line option to gcc:

$ gcc @options helloworld.c -o helloworld

Keeping your gcc compiler options in an options file makes managing multiple command-line options easy.


Do you want to receive a compilation of Wazi's top
blog posts in the past year delivered directly to your inbox?






This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

Comments

Tag heuer watches as a global luxury sales wrist watch brands in the top five, demonstrating, tag heuer watches have been loved by the people.No matter men or women should have a tag heuer watches.Expensive price tag heuer watch, of course, the tag heuer replica watches appeared in the watch market, with a tag heuer watch is no longer a difficult task.Don't need $200 you can get a high quality tag heuer replica watches http://www.tagheuerwatch.net/, go to the choose and buy one.
Posted @ Wednesday, February 19, 2014 12:41 AM by jasonwongoo
 
When you order one or more Designer Handbags or wallets from SIGHTFOCUS, your satisfaction, in our product and our unparalleled customer service, is fully guaranteed. It is a Repliques de Montresguarantee we make with the utmost confidence, having never received a single complaint regarding the quality of our Discount Designer Handbags. But don’t take our word for it - check out our testimonial page for proof that Cheap Replicas when you order from us, you order in style!
Posted @ Friday, June 06, 2014 10:13 PM by kenny
Even if you'll have to enroll some friendly event maybe a business enterprise and congregate, chanel replica bags make certain typically the handbag you ought to are actually using syncs easily utilizing your wear. fake hublot Typically the comfort with the garment are generally developed healthier with the help of greatly complimented trendy purses displayed completely different establishments. prada replica The best reasons for having such purses might be that they turn out to be had with the help of most of attires, and yet positively an outstanding meet should be used which means this is not to affect a synchronization. chanel replica bags But, much of if you find yourself worried about the amount paid for these wholesale handbags for women. replica chanel And yet the good thing is who most purses can be obtained by budget friendly not to mention economical levels because of web stores. 
Posted @ Sunday, September 28, 2014 1:12 AM by xxccc
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics