Wonderful GCC Tour (2)

Source: Internet
Author: User
Tags add numbers
A wonderful trip to GCC (II)-Linux general technology-Linux programming and kernel information. The following is a detailed description. Code optimization

Code optimization means that the compiler analyzes the source code, finds out the part that has not yet reached the optimal value, and re-combines it to improve the execution performance of the program. The code optimization function provided by GCC is very powerful. It controls the generation of optimization code through the compilation option-On, where n is an integer representing the optimization level. For GCC of different versions, the value range of n and its corresponding optimization effects may be different. The typical range is from 0 to 2 or 3.

The option-O can be used during compilation to tell GCC to reduce the code length and execution time at the same time. The effect is equivalent to-O1. The types of optimizations that can be performed at this level depend on the target processor, but they generally include Thread Jump and Deferred Stack Pops. Option-O2 tells GCC not only to complete all-O1-level optimization, but also to make some extra adjustments, such as processor command scheduling. In addition to completing all-O2-level optimization, option-O3 also includes loop expansion and other optimizations related to the processor features. Generally, the larger the number, the higher the optimization level, and the faster the program runs. Many Linux programmers like to use the-O2 option because it achieves an ideal balance between the optimized length, Compilation Time, and code size.

The following describes the GCC code optimization function through a specific instance. The program used is shown in listing 3.

Listing 3: optimize. c

# Include
Int main (void)
{
Double counter;
Double result;
Double temp;
For (counter = 0;
Counter <2000.0*2000.0*2000.0/20.0 + 2020;
Counter + = (5-1)/4 ){
Temp = counter/1979;
Result = counter;
}
Printf ("Result is % lfn", result );
Return 0;
}



Compile without any Optimization Options:

# Gcc-Wall optimize. c-o optimize



With the time Command provided by Linux, You can roughly calculate the time required for running the program:

# Time./optimize
Result is 400002019.000000
Real 0m14. 942 s
User 0m14. 940 s
Sys 0m0. 000 s



Next, use the optimization options to optimize the Code:

# Gcc-Wall-O optimize. c-o optimize



Test the running time again under the same conditions:

# Time./optimize
Result is 400002019.000000
Real 0m3. 256 s
User 0m3. 240 s
Sys 0m0. 000 s



Comparing the output results of the two executions, it is not difficult to see that the program performance has indeed been greatly improved, from 14 seconds to 3 seconds. This example is specially designed for the optimization function of GCC, so the execution speed of the program before and after optimization has greatly changed. Although the GCC code optimization function is very powerful, as an excellent Linux programmer, we must first strive to be able to manually write high-quality code. If the written code is short and logical, the compiler will not do more work, or even require no optimization at all.

Although optimization can bring better execution performance to the program, you should avoid optimizing the Code in the following scenarios:

◆ The higher the optimization level during program development, the longer the compilation time will be spent. Therefore, it is best not to use optimization options during development. Only when the software release or development ends, to optimize the final generated code.

◆ When resources are limited, some optimization options will increase the size of executable code. If the memory resources that the program can apply for at runtime are very tight (such as some real-time embedded devices ), do not optimize the code, because the negative effects may have very serious consequences.

◆ Some codes may be deleted or rewritten during code optimization during tracking and debugging, or reorganized to achieve better performance, this makes tracking and debugging difficult.

Debugging

A powerful debugger not only provides programmers with the means to track program execution, but also helps them find a solution to the problem. For Linux programmers, GDB (GNU Debugger) works with GCC to provide a complete debugging environment for Linux-based software development.

By default, GCC does not insert debugging symbols into the generated binary code during compilation, because this increases the size of executable files. If you need to generate debugging symbol information during compilation, you can use the-g or-ggdb option of GCC. When GCC generates debugging symbols, it also adopts a hierarchical approach, developers can add numbers 1, 2, or 3 after the-g option to specify the number of debugging information added to the Code. The default value is 2 (-g2). The generated debugging information includes extended symbol table, row number, local or external variable information. Level 3 (-g3) contains all debugging information in Level 2 and macros defined in source code. Level 1 (-g1) does not contain local variables and debugging information related to row numbers, so it can only be used for tracing and stack dumping. Tracing refers to the function call history during the running process of the monitoring program. Stack dumping is a method to save the execution environment of the program in the original hexadecimal format, both are commonly used debugging methods.

Debugging symbols generated by GCC are universally adaptive and can be used by many debuggers. However, if GDB is used, you can also use the-ggdb option to include the debugging information dedicated to GDB in the generated binary code. The advantage of this method is that it can facilitate debugging of GDB, but the disadvantage is that other debuggers (such as DBX) may not be able to perform normal debugging. Option-ggdb accepts the same debugging level as-g, which has the same impact on the output debugging symbols.

Note that any debugging option will increase the size of the final binary file and increase the overhead of the program during execution, therefore, debugging options are generally used only in the software development and debugging phase. The impact of debugging options on the size of generated code can be seen from the following comparison process:

# Gcc optimize. c-o optimize
# Ls optimize-l
-Rwxrwxr-x 1 xiaowp 11649 Nov 20 optimize (debug option not added)
# Gcc-g optimize. c-o optimize
# Ls optimize-l
-Rwxrwxr-x 1 xiaowp 15889 Nov 20 optimize (add debugging options)



Although debugging options increase the file size, many software in Linux still use debugging options for compilation in the test version or even the final release version, this is a distinctive feature of Linux.

The following uses a specific example to describe how to analyze errors using debugging symbols. The program used is shown in Listing 4.

Listing 4: crash. c

# Include
Int main (void)
{
Int input = 0;
Printf ("Input an integer :");
Scanf ("% d", input );
Printf ("The integer you input is % dn", input );
Return 0;
}



Compile and run the above Code to generate a serious segment error (Segmentation fault) as follows:

# Gcc-g crash. c-o crash
#./Crash
Input an integer: 10
Segmentation fault



To locate errors more quickly, you can use GDB for tracking and debugging as follows:

# Gdb crash
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
......
(Gdb)



When the GDB prompt appears, it indicates that GDB is ready for debugging. Now you can run the program under GDB monitoring by running the run command:

(Gdb) run
Starting program:/home/xiaowp/thesis/gcc/code/crash
Input an integer: 10

Program received signal SIGSEGV, Segmentation fault.
0x4008576b in _ IO_vfscanf_internal () from/lib/libc. so.6



After carefully analyzing the output results provided by GDB, it is not difficult to see that the program is aborted due to a segment error, which indicates that the memory operation is faulty, the specific problem occurs when _ IO_vfscanf_internal () is called. To obtain more valuable information, you can use the backtrace command backtrace provided by GDB. The execution result is as follows:

(Gdb) backtrace
#0 0x4008576b in _ IO_vfscanf_internal () from/lib/libc. so.6
#1 0xbffff0c0 in ?? ()
#2 0x4008e0ba in scanf () from/lib/libc. so.6
#3 0x08048393 in main () at crash. c: 11
#4 0x40042917 in _ libc_start_main () from/lib/libc. so.6



Skip the first three rows in the output result. From the fourth row of the output result, it is not difficult to see that GDB has fixed the error to row 11th in crash. c. Check carefully:

(Gdb) frame 3
#3 0x08048393 in main () at crash. c: 11
11 scanf ("% d", input );



Use the frame Command provided by GDB to locate the code segment with an error. The value following this command can be found at the beginning of the line in the output result of the backtrace command. The error has been found.

Scanf ("% d", input );
Change
Scanf ("% d", & input );



After completion, you can exit GDB. The command is as follows:

(Gdb) quit



GDB has far more functions than that. It can also track programs, check memory variables, and set breakpoints in one step.

The intermediate results generated by the compiler may be used during debugging. You can use the-save-temps option to enable GCC to save the pre-processing code, assembly code, and target code as files. If you want to check whether the generated code can be manually adjusted to improve the execution performance, the intermediate file generated during the compilation process will be very helpful, as shown in the following figure:

# Gcc-save-temps foo. c-o foo
# Ls foo *
Foo. c foo. I foo. s



Other debugging options supported by GCC include-p and-pg, which add Profiling information to the final binary code. Profiling is helpful for identifying program performance bottlenecks and a powerful tool to help Linux programmers develop high-performance programs. When the-p option is added during compilation, statistical information that can be recognized by the general profiling tool (Prof) will be added to the generated code, while the-pg option generates only the GNU profiling tool (Gprof) the statistical information that can be identified.

Note: Although GCC allows debugging Symbol Information to be added while optimizing, the optimized code will be a great challenge for debugging itself. After the code is optimized, the variables declared and used in the source program may not be used any more, and the control flow may suddenly jump to an unexpected place, loop statements may become everywhere because of loop expansion. All these are a nightmare for debugging. It is recommended that you do not use any optimization options during debugging. optimization is considered only when the program is finally released.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.