Introduction to C development tools in Linux-general Linux technology-Linux programming and kernel information. The following is a detailed description. The Linux release contains many software development tools. many of them are used for C and C ++ application development. this article describes the tools that can be used for C application development and debugging in Linux. the purpose of this article is to introduce how to use the C compiler and other C programming tools in Linux, rather than the C Programming Tutorial.
Gnu c Compiler
The gnu c compiler (GCC) is a fully functional ansi c-compatible compiler. if you are familiar with a C compiler on other operating systems or hardware platforms, you will be able to quickly master GCC. this section describes how to use GCC and some of the most common options for GCC compilers.
Use GCC
The basic usage of the GCC compiler. gcc command is usually followed by some options and file names:
Gcc [options] [filenames]
The operation specified by the command line option will be executed on each given file on the command line. The next section describes the options you will most commonly use.
GCC options
GCC has more than 100 compilation options available. many of these options may never be used, but some of the main options will be frequently used. many GCC options include more than one character. therefore, you must specify the respective characters for each option, and, just like most Linux commands, you cannot separate the characters with a group of options. for example, the following two commands are different:
Gcc-p-g test. c
Gcc-pg test. c
The First Command tells GCC to compile test. in c, the profile information is created for the prof command and the debugging information is added to the executable file. the second command only tells GCC to create profiling information for the gprof command.
When you do not need any options to compile a program, GCC will create (assuming the compilation is successful) a program named. out executable file. for example, the following command will generate. out file:
Gcc test. c
You can use the-o compilation option to specify a file name for the generated executable file instead of. out. for example. the c program of C is compiled into an executable file named count. Enter the following command:
GCC also has the compilation option to specify how much the compiler processes. -c indicates that GCC only compiles the source code as the target code and skips the Assembly and connection steps. this option is frequently used because it makes compilation of multiple C Programs faster and easier to manage. the target code file created by GCC is missing. o Extension.
The-S compilation option tells GCC to stop compiling after an assembly language file is generated for C code. the default extension of assembly language files generated by GCC is. s. -E indicates that the compiler only processes the input file. when this option is used, the pre-processor output is sent to the standard output instead of stored in the file.
Optimized items
When you use GCC to compile C code, it will try to complete the compilation at least and make the compiled code easy to debug. easy debugging means that the compiled code has the same execution order as the source code, and the compiled code has not been optimized. there are many options that can be used to tell GCC to generate a smaller value based on more Compilation Time and easier debugging.
Faster executable files. The most typical options are-O and-O2.
The-O option tells GCC to optimize the source code. in most cases, these optimizations make program execution faster. -The O2 option tells GCC to generate code as small as possible and as fast as possible. the-O2 option will make compilation faster than-O. however, code execution is usually faster.
In addition to the-O and-O2 optimization options, there are also some low-level options for generating faster code. these options are very special, and it is best to use them only when you fully understand the effects these options will have on the compiled code. for a detailed description of these options, refer to the GCC guide page and type man gcc on the command line.
Debugging and profiling options
GCC supports several debugging and profiling options. Among these options,-g and-pg options are most commonly used.
The-g option tells GCC to generate debugging information that can be used by the GNU Debugger to debug your program. GCC provides a feature that is not available in many other C compilers. in GCC, you can combine-g with-O (to produce Optimized Code .. this is useful because you can debug your code as close as possible to the final product. when you use these two options at the same time, you must be aware that some of your code has been modified by GCC during optimization. about debugging
For more information about the C program, see the next section "Debug C program with gdb ".
-The pg option tells GCC to add additional code to your program. During execution, gprof profiling information is generated to show the time consumption of your program. for more information about gprof, see "gprof.
Debug the GCC program with gdb
Linux contains a GNU debugging program called gdb. gdb is a powerful debugger used to debug C and C ++ programs. it enables you to observe the internal structure and memory usage of the program while the program is running. the following are some functions provided by gdb:
It enables you to monitor the value of variables in your program.
It enables you to set breakpoints so that the program stops running on the specified code line.
It enables you to execute your code in one row.
Type gdb on the command line and press the Enter key to run gdb. If everything works properly, gdb will be started and you will see similar content on the screen:
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux ".
(Gdb)
After you start gdb, you can specify many options on the command line. You can also run gdb in the following ways:
:
Gdb ;
When you run gdb in this way, you can directly specify the program to be debugged. this tells gdb to mount the executable file named fname. you can also use gdb to check a core file generated when the program ends abnormally,
You can also connect to a running program. You can refer to the gdb guide page or Type gdb-h on the command line to get a simple list of instructions on these options.
Compile the Code for Debugging (Compiling Code for Debugging)
To make gdb work normally, you must make your program contain debugging information during compilation. the debugging information includes the type of each variable in your program, the address ing in the executable file, and the source code line number. gdb uses this information to associate the source code with the machine code.
Enable the debugging option with the-g option during compilation.
Gdb basic commands
Gdb supports many commands to enable different functions. these commands are loaded from simple files to complex commands that allow you to check the stack content you are calling. Table 27.1 lists some of the commands you will use when debugging with gdb. for details about how to use gdb, refer to the Guide page of gdb.
Basic gdb commands.
Description
File to load the executable file to be debugged.
Kill to terminate the program being debugged.
List lists part of the source code that generates the execution file.
Next, execute a line of source code but do not enter the function.
Step: execute a line of source code and enter the function.
Run to execute the program currently being debugged
Quit terminate gdb
Watch enables you to monitor the value of a variable, regardless of when it is changed.
Print display expression value
Break sets breakpoints in the code, which will cause the program to be suspended when it is executed here.
Make enables you to re-generate executable files without exiting gdb.
Shell enables you to run UNIX shell commands without leaving gdb.
Gdb supports many command editing features similar to those of UNIX shell programs. you can press the Tab key like in bash or tcsh to allow gdb to help you complete a unique command. If it is not unique, gdb will list all matching commands. you can also use the mouse key to flip up and down History commands.
Gdb application example
This section uses an example to teach you how to debug a program with gdb step by step. The program to be debugged is quite simple, but it shows typical applications of gdb.
The program to be debugged is listed below. This program is called "hello", which displays a simple greeting and is listed in reverse order.
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++)
String2 [size-I] = string;
String2 [size + 1] = '';
Printf ("The string printed backward is % s", string2 );
}
Compile it with the following command:
Gcc-g-o hello. c
The following results are displayed when the program is executed:
../Hello
The string is hello world!
The string printed backward is
The first line of output is correct, but the output in the second line is not what we expected.
It should be:
The string printed backward is! Dlrow olleh
For some reason, the my_print2 function does not work properly. Let's use gdb to see where the problem is,
First, enter the following command:
If you forget to pass the program to be debugged as a parameter when entering the command to gdb, you can use
File command to load it:
(Gdb) file hello
This command will load the hello executable file just as you load it in the gdb command line.
You can use the gdb run Command to run hello. When it is run in gdb, the result will be like this:
(Gdb) run
Starting program:/root/hello
The string is hello world!
The string printed backward is
Program exited with code 040
The output is the same as the running result outside gdb. The question is, why does reverse printing not work? To find out the crux of the problem, we can set a breakpoint after the for statement of the my_print2 function. The specific method is
Enter the list Command three times at the prompt to list the source code:
If you press enter, gdb will execute the list command again and give the following output:
11}
12
13 void my_print (char * string)
14 {
15 printf ("The string is % s", string );
16}
17
18 void my_print2 (char * string)
19 {
20 char * string2;
Press enter again to list the remaining parts of the hello program:
21 int size, I;
22
23 size = strlen (string );
24 string2 = (char *) malloc (size + 1 );
25 for (I = 0; I <size; I ++)
26 string2 [size-I] = string;
27 string2 [size + 1] = '';
28
29 printf ("The string printed backward is % s", string2 );
30}
Based on the listed source program, you can see that the place where the breakpoint is to be set is in line 26th. At the gdb command line prompt, type the following command to set the breakpoint:
(Gdb) break 26
Gdb will make the following response:
Breakpoint 1 at 0x804857c: file hello. c, line 26.
(Gdb)
Enter the run Command to generate the following output:
Starting program:/root/hello
The string is hello world!
Breakpoint 1, my_print2 (string = 0xbffffab0 "hello world! ") At hello. c: 26
26 string2 [size-I] = string;
You can set an observation point to observe the value of the string2 [size-I] variable to see how errors occur,
The method is to enter:
(Gdb) watch string2 [size-I]
Gdb will respond as follows:
Hardware watchpoint 2: string2 [size-I]
Now we can use the next command to execute the for loop step by step:
(Gdb) next
After the first loop, gdb tells us that the value of string2 [size-I] Is 'H'. gdb uses the following display to tell you this information:
Hardware watchpoint 2: string2 [size-I]
Old value = 0 '00'
New value = 104 'H'
My_print2 (string = 0xbffffab0 "hello world! ") At hello. c: 25
25 for (I = 0; I <size; I ++)
This value is expected. The results of subsequent cycles are correct. When I = 11, the expression
The value of string2 [size-I] is equal '! ', The value of size-I is equal to 1, and the last character has been copied to the new string.
If you run the loop again, you will see that no value is allocated to string2 [0], and it is the first character of the new string, because the malloc function initializes them as null characters when allocating memory. therefore, the first character of string2 is a null character. this explains why there is no output when string2 is printed.
It is very easy to correct the problem after finding out the problem. you have to change the offset of the first character written to string2 in the code to size-1 instead of size. this is because the size of string2 is 12, but the starting offset is 0. The characters in the string are offset 0 to offset 10, and the offset 11 is reserved as null characters.
The correction method is very simple. This is the code for this solution:
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++)
String2 [size-1-I] = string;
String2 [size] = '';
Printf ("The string printed backward is % s", string2 );
}
If the program generates a core file, you can use the gdb hello core Command to view the program's errors. For example, in the my_print2 () function, if you forget to allocate the memory string2 = (char *) malloc (size + 1) to string2, it is likely that the core dump will be performed.
Other C programming tools
Xxgdb
Xxgdb is a graphical interface of gdb Based on the X Window System. xxgdb includes all the features of gdb in the command line version. xxgdb allows you to execute Common commands by pressing the button. the place where the breakpoint is set is also displayed in graphs.
You can run the following command in an Xterm window:
Xxgdb
You can use any valid command line options in gdb to initialize xxgdb. In addition, xxgdb also has some special command line options. Table 27.2 lists these options.
Table 27.2. xxgdb command line options.
Description
Db_name specifies the name of the debugger used. The default value is gdb.
Db_prompt specifies the debugger prompt. The default value is gdb.
Gdbinit specifies the name of the command file that initializes gdb. The default value is. gdbinit.
Nx tells xxgdb not to execute the. gdbinit file.
Bigicon uses a large icon.
CILS
You can use the following path on the sunsite.unc.edu FTP site:
/Pub/Linux/devel/lang/c/calls.tar. Z
To obtain CILS, some earlier versions of the Linux CD-ROM release is also included. because it is a useful tool, we will introduce it here. if you find it useful, get a copy from BBS, FTP, or another CD-ROM. CILS calls the pre-processor of GCC to process the given source program files, and then outputs the function call tree in these files.
Note: After you log on to your system as a Super User, perform the following steps: 1. decompress and untar files. 2. the sub-directory created after the cd enters calluntar. 3. move the file named CILS to the/usr/bin directory. 4. move the file named calls.1 to the/usr/man/man1 directory. 5. delete the/tmp/CILS directory. these steps will install the CILS program and its Guide page on your system.
When the call trace result is printed by CILS, the file name of the file where the function is located is given in brackets after the function:
Main [hello. c]
If the function is not in the file provided to CILS, and does not know where the called function comes from, only the function name is displayed:
Printf
CILS does not output recursive and static functions. recursive functions are shown as follows:
Fact <recursive in factorial. c>; >;>;
Static functions are shown as follows:
Total [static in calculate. c]
As an example, we assume that the following program is processed with cballs:
Void count_sum ()
{
Int I, sum = 0;
For (I = 0; I <1000000; I ++)
Sum + = I;
}
Void my_print (char * string)
{
Count_sum ();
Printf ("The string is % s", string );
}
Void my_print2 (char * string)
{
Char * string2;
Int size, I, sum = 0;
Count_sum ();
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++) string2 [size-1-I] = string;
String2 [size] = '';
For (I = 0; I <5000000; I ++)
Sum + = I;
Printf ("The string printed backward is % s", string2 );
}
The following output is generated:
1 _ underflow [hello. c]
2 main
3 my_print [hello. c]
4 count_sum [hello. c]
5 printf
6 my_print2 [hello. c]
7 count_sum
8 strlen
9 malloc
10 printf
CILS has many command line options to set different output formats. For more information about these options, refer to the CILS guide page. The method is to type CILS-h on the command line.
Calltree
The calltree is similar to CILS. Besides the output function call tree, there are other detailed information. You can use the following path from the sunsite.unc.edu FTP site
:/Pub/Linux/devel/lang/c/calltree.tar.gz get calltree.
Cproto
Cproto reads the C source program file and automatically generates prototype declarations for each function. Using cproto can save you a lot of time to define the function prototype when writing a program.
If you want cproto process the following code (cproto hello. c ):
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++)
String2 [size-1-I] = string;
String2 [size] = '';
Printf ("The string printed backward is % s", string2 );
}
You will get the following output:
/* Hello. c */
Int main (void );
Int my_print (char * string );
Int my_print2 (char * string );
This output can be redirected to an inclusion file that defines the function prototype.
Indent
The indent utility is another programming utility included in Linux. in short, this tool produces beautiful indent formats for your code. indent also has many options to specify how to format your source code. for more information about these options, see the indent guide. On the command line, type indent-h.
The following example shows the default output of indent:
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++) string2 [size-1-I] = string;
String2 [size] = '';
Printf ("The string printed backward is % s", string2 );
}
C code after running indent:
# Include ;
Static void my_print (char *);
Static void my_print2 (char *);
Main ()
{
Char my_string [] = "hello world! ";
My_print (my_string );
My_print2 (my_string );
}
Void
My_print (char * string)
{
Printf ("The string is % s", string );
}
Void
My_print2 (char * string)
{
Char * string2;
Int size, I;
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++)
String2 [size-1-I] = string;
String2 [size] = '';
Printf ("The string printed backward is % s", string2 );
}
Indent does not change the essence of the code, but just changes the appearance of the Code to make it more readable. This is always a good thing.
Gprof
Gprof is a program installed in the/usr/bin directory of your Linux system. It allows you to parse your program to know which part of the program is most time-consuming during execution.
Gprof will tell you the number of calls to each function in the program and the percentage of time each function is executed. This information is useful if you want to improve the performance of your program.
To use gprof in your program, you must add the-pg option when compiling the program. this will make the program generate a gmon every execution. out file. gprof uses this file to generate profiling information.
After you run your program and generate the gmon. out file, you can use the following command to obtain the profiling information:
Gprof ;
The program_name parameter is the name of the program that generates the gmon. out file.
To illustrate the problem, the count_sum () function is added to the program to consume CPU time. The program is as follows:
# Include ;
Void count_sum ()
{
Int I, sum = 0;
For (I = 0; I <1000000; I ++)
Sum + = I;
}
Void my_print (char * string)
{
Count_sum ();
Printf ("The string is % s", string );
}
Void my_print2 (char * string)
{
Char * string2;
Int size, I, sum = 0;
Count_sum ();
Size = strlen (string );
String2 = (char *) malloc (size + 1 );
For (I = 0; I <size; I ++) string2 [size-1-I] = string;
String2 [size] = '';
For (I = 0; I <5000000; I ++)
Sum + = I;
Printf ("The string printed backward is % s", string2 );
}
$ Gcc-pg-o hello. c
$./Hello
$ Gprof hello | more
The following output will be generated:
Flat profile:
Each sample counts as 0.01 seconds.
% Cumulative self total
Time seconds callus/call us/call name
69.23 0.09 0.09 1 90000.00 103333.33 my_print2
30.77 0.13 0.04 3 13333.33 13333.33 count_sum
0.00 0.13 0.00 2 0.00 13333.33 my_print
% Total time occupied by executing this function
Percentage of time execution time
Cumulative seconds elapsed time to execute this function
Seconds (including the time it takes for this function to call other functions)
Time consumed by self to execute this function
Seconds (the time spent calling other functions is not counted)
Number of CILS calls
Self: The microseconds that this function takes to execute.
Us/call
Total execute this function and add it to call other functions.
Us/call time in microseconds
Name function name
From the data above, we can see that it takes no time to execute the my_print () function, but it calls
Count_sum () function, so the cumulative number of seconds is 0.13.
Tip: gprof generates a large amount of profiling data. If you want to check the data, you 'd better redirect the output to a file.
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.