There is a lot of software development tools in the release of Linux. Many of them are developed for C and C applications. This article describes tools that can be used for C applications and debugging under Linux. The main purpose of this article describes how to use C compilers and other C programming tools under Linux, not C language programming tutorials. In this article, you will learn the following knowledge:
· What is C
· GNU C compiler
· Use GDB to debug GCC application
You can also see other useful C programming tools issued with Linux. These tools include PRETTY Print Programs, additional debugging tools, Automatic Function Prototypers.
Note: The PRETTY Print Programs automatically helps you format the source code to generate a consistent indentation format.
What is C?
C is a generally used universal programming language in the early days of UNIX operating systems. It was first written by Dennis Ritchie of Bell Lab for UNIX, and UNIX was written in assembly language and a language called B. From then on, C became the most widely used computer language in the world.
C can be found in the programming field:
· It is a very common language. Almost you can think of at least one of the available C compilers. And its grammar and function library are unified on different platforms. This feature is very attractive to developers.
· The speed of writing with C is very fast.
· C is a system language on all versions of UNIX.
C has a great development in the past twenty years. A C language standard called ANSI C is released in the Final At the end of the 1980s. The American National Standards Institute is released. This ensures the consistency of C in the future in different platforms. In the 1980s, an object-oriented extension called C . C will be described in another article "C Programming".
The C compiler available on Linux is a GNU C compiler, which is built on the program license of the Free Software Foundation, so it can be freely released. You can find it on Linux's distribution disc.
GNU C compiler
The GNU C compiler (GCC) issued with Slackware Linux is a full-featured ANSI C compatible compiler. If you are familiar with a C compiler on other operating systems or hardware platforms, you will be able to master GCC quickly. This section describes how to use the GCC and some of the most common options for some GCC compilers.
Use GCC
Typically followed by some options and file names using the GCC compiler. The basic usage of the GCC command is as follows:
GCC [Options] [filenames]
The operation specified by the command line option will be executed on each of the files given on the command line. The next section will narrate some options you will use.
GCC option
GCC has more than 100 compilation options available. Many of these options you may never use, but some main options will be used frequently. Many GCC options include more than one character. So you must specify your respective hyphens for each option, just like most Linux commands, you can't follow a set of options after a separate hyphen. For example, the following two commands are different:
GCC -P -G Test.c
GCC -PG Test.c
The first command tells the GCC to build a profile information for the PROF command and add the debug information to the executable file when compiling TEST.C. The second command only tells the GCC to establish a profiling information for the gprof command.
When you don't have any options to compile a program, GCC will establish (assuming compile success) a executable name called A.out. For example, the following command will generate a file called A.out in the current directory:
GCC Test.c
You can use the -o compilation option to specify a file name for the generated executable. For example, compiling a C program called Count.c into a executable called count, you will enter the following command: gcc -o count country.c
Note: When you use the -o option, the -o must follow a file name.
The GCC also has the compilation option for specifying the compiler processing. The -c option tells the GCC to skip the assembly and connection of the source code as a target code. This option is used very frequently because it makes it easier when compiling multiple C programs faster and easier to manage. The target code file established by the GCC has a .o extension.
The -s compilation option tells GCC to stop compiling after the assembly language file is generated for C code. The default extension of the assembly language file generated by the GCC is .S. The -e option indicates that the compiler is only preprocessing the input file. When this option is used, the output of the preprocessor is sent to the standard output instead of being stored in the file.
Optimization option
When you use GCC to compile C code, it will try to compile with the least amount of time and make the compiled code easy to debug. Easy to debug means that the compiled code is the same 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 smaller and faster executables on the basis of consuming more compile time and sacrifice. The most typical in these options is -O and -O2 options.
The -o option tells the GCC to optimize the source code. These optimizations will make the program faster in most cases. -O2 option tells GCC to generate as small and as fast as possible. -O2 option will slow compilation speed than using -O -O. But usually generated code execution speed will be faster.
In addition to the -O and -O2 optimization options, there are some low-level options to produce faster code. These options are very special, and it is best to use when you fully understand these options will be used when the compiled code is generated. Detailed description of these options, please refer to the GCC's guide page, type the Man GCC on the command line.
Debug and parsing options
GCC supports several debugging and profiling options. The -g and -pg options are most common in these options.
The -g option tells the GCC to generate debugging information that can be used by the GNU debugger to debug your program. GCC provides a lot of features in many other C compilers that you can use in the GCC you can use. This is very useful because you can debug your code with the final product as possible. When you use these two options at the same time, you must know that some code you have written is already modified by GCC when optimized. For more information on debugging C procedures, please see the "GDB debug C program".
-pg Option Tell GCC to add additional code in your program, execute, generate the profiling information of Gprof to display the time consumption of your program. For more information on GPROF, please refer to the "GPROF" section.
Debug GCC program with GDB
Linux contains a GNU debugger called GDB. GDB is a powerful debugger for debugging C and C programs. It allows you to observe the internal structure and memory usage of the program at runtime. The following is some of the features provided by GDB:
· It allows you to monitor the value of variables in your program.
· It allows you to set breakpoints to stop execution on the specified code line.
· It makes you execute your code a line.
Type GDB on the command line and press Enter to run GDB, if everything is normal, GDB will be started and you will see similar content on the screen:
GDB Is Free Software and You Are Welcome to 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.
GDB 4.14 (I486-SLAKWARE-Linux), Copyright 1995 Free Software Foundation, Inc. (GDB)
When you start GDB, you can specify a lot of options on the command line. You can also run GDB in the following ways:
GDB
When you run GDB in this way, you can specify the program you want to debug. This will tell GDB to load an executable named FNAME. You can also use GDB to check an Core file that is generated by an exception, or connects with 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.
Compilant code for debugging
In order to make GDB work normally, you must make your program contain debug information when compiling. The debugging information contains the type of each variable in your program and the number of address mappings in the executable and the line number of the source code. GDB uses this information to associate the source code and the machine code.
Turn on the debug option with the -g option when compiling.
GDB basic order
GDB supports a lot of commands to make you can achieve different features. These commands are loaded from simple files to the complex commands that allow you to check the call content called, Table 27.1 lists some of the commands you use when you use GDB debugging. For more information on GDB, please refer to the GDB guide page.
Table 27.1. Basic GDB Command.
Command description
File loads the executable you want to debug.
Kill terminates the program being debugging.
List executes a source code but does not enter the inside of the function.
NEXT executes a source code but does not enter the inside of the function.
STEP performs a row source code and enters the inside of the function.
Run executes the current debugged program
Quit termination GDB
Watch allows you to monitor the value of a variable regardless of whether it is changed.
Break sets breakpoints in the code, which will hang it when the program is executed here.
Make allows you to re-generate executables without exiting GDB.
The shell allows you to execute the UNIX shell command without leaving GDB.
GDB supports a lot of command editing features like UNIX shell programs. You can press the Tab button like it in Bash or TCSH to make GDB to help you fill a unique command, if the GDB will list all the matching commands if the GDB will list all match. You can also flip history commands with cursor keys.
GDB application example
This section teaches you step by step with a GDB debugging program. The debugged program is quite simple, but it shows the typical application of GDB.
The program that will be debugged will be listed below. This program is called Greeting, which shows a simple greeting and listed it in the back sequence.
#include
Main ()
{
Char my_string [] = "Hello there";
MY_PRINT (my_string);
MY_PRINT2 (my_string);
}
void my_print (char * string)
{
Printf ("THE STRING IS% S / N", String);
}
Void my_print2 (char * string)
{
Char * string2;
Int size, i;
SIZE = Strlen (String);
String2 = (char *) Malloc (SIZE 1);
For (i = 0; i String2 [size - i] = string [i]; String2 [SIZE 1] = `/ 0; Printf ("THE STRING Printed Backward IS% S / N", String2); } Compile it with the following command: GCC -O Test Test.c The following results displayed when this program is executed: The string is hello there The first line of the String Printed Backward IS output is correct, but the second line print is not what we expect. The output we envisage should be: The String Printed Backward Is Ereht Olleh For some reason, my_print2 functions do not work properly. Let us use GDB to see where there is, type the following command: GDB GRETING Note: Remember to open the debug option when compiling the Greeting program. If you forget to pass the program you want to debug as a parameter, you can load it with the file command under the GDB prompt: (GDB) File Greeting This command will load the Greeting executable is like you to load it in the GDB command line. At this point you can run Greeting with GDB's Run command. When it is running in GDB, the result is about like this: (GDB) RUN Starting program: / root / greeting The string is hello there The String Printed Backward IS Program evted with code 041 This output is the same as the result of running outside the GDB. The problem is, why don't you work in the reverse order? In order to find out the crux, we can set a breakpoint after the FOR statement of my_print2 functions, and the specific approach is to type the list command three times in the GDB prompt, list the source code: (GDB) List (GDB) List (GDB) List Tip: Press Enter to return to the car at the GDB prompt. The output of the first type of list command is as follows: 1 #include 2 3 main () 4 { 5 char my_string [] = "Hello there"; 6 7 my_print (my_string); 8 my_print2 (my_string); 9 } 10 If you press Enter, GDB will execute a list command, give the following output: 11 my_print (char * string) 12 { 13 Printf ("THE STRING IS% S / N", String); 14} 15 16 my_print2 (char * string) 17 { 18 char * string2; 19 Int size, i; 20 Pressing a cycle will list the remaining parts of the Greeting program: 21 size = strlen (String); 22 string2 = (char *) Malloc (SIZE 1); 23 for (i = 0; i 24 string2 [size - i] = String [i]; 25 string2 [size 1] = `/ 0; 26 Printf ("THE STRING Printed Backward IS% S / N", String2); 27} Based on the source program listed, you can see where you want to break points on line 24, type the following command to set breakpoints under the GDB command line prompt: (GDB) BREAK 24 GDB will make the following response: Breakpoint 1 AT 0x139: File Greeting.c, Line 24 (GDB) Now type the RUN command, will generate the following output: Starting program: / root / greeting The string is hello there Breakpoint 1, My_Print2 (String = 0xBffFDC4 "Hello there") at Greeting.c: 2424 string2 [size-i] = string [i] You can see how the error is generated by setting an observation point of the value of the string2 [size - i] variable, the practice is to type: (gdb) Watch string2 [size - i] GDB will make the following response: WatchPoint 2: String2 [size - i] Now you can use the next command to perform the for loop for a step: (GDB) Next After the first cycle, GDB tells us that the value of string2 [size - i] is `h`. GDB tells you this information with the following display: WatchPoint 2, String2 [Size - I] Old value = 0 `/ 000 New value = 104 `h MY_PRINT2 (String = 0xBfffdc4 "Hello there") at Greeting.c: 23 23 for (i = 0; i This value is expected. The result of the subsequent cycle is correct. When i = 10, the value of expression string2 [size - i] is equal to `E., Size - i is equal to 1, and the last character has been copied to the new string. If you do the loop again, you will see that there is no value assigned to string2 [0], and it is the first character of the new string, because the malloc function initials them into empty (null) characters when allocating memory . So the first characters of String2 are empty characters. This explains why there is no output when printing String 2. Now find out where the problem is, correct this error is very easy. You have to change the offset of the first character written in the code to SIZE - 1 instead of size. This is because String2 is 12, but the start offset is 0, the character in the string from the offset 0 to the offset amount 10, the offset amount 11 is empty characters. In order to make the code work properly, there are many modifications. One is a variable that is another actual size of the actual size than the string. This is the code of this solution: #include Main () { Char my_string [] = "Hello there"; MY_PRINT (my_string); MY_PRINT2 (my_string); } MY_PRINT (Char * String) { Printf ("THE STRING IS% S / N", String); } MY_PRINT2 (Char * String) { Char * string2; Int size, size2, i; SIZE = Strlen (String); Size2 = Size -1; String2 = (char *) Malloc (SIZE 1); For (i = 0; i String2 [Size2 - I] = String [i]; String2 [size] = `/ 0; Printf ("THE STRING Printed Backward IS% S / N", String2); } Another C programming tool Slackware Linux also includes some C development tools we have not mentioned. This section will introduce these tools and their typical usage. xxgdb XXGDB is a graphical interface based on the x Window system. The XXGDB includes all features on the gdb of the command line. XXGDB allows you to perform a commonly used command by pressing the button. The place where the breakpoint is set is also displayed. You can use the commands below in an XTERM window to run it: xxgdb You can initialize XXGDB in any valid command line option in GDB. In addition, XXGDB also has some unique command line options, and these options are listed in Table 27.2. Table 27.2. Xxgdb command line option. Selection DB_NAME Specifies the name of the debugger used, the default is GDB. DB_PROMPT specifies the debugger prompt, default is GDB. GDBINIT specifies the file name of the initialization of the command file of GDB, default is .gdbinit. NX tells xxgdb does not execute .Gdbinit file. Bigicon uses a large icon. Calls You can use the following path in the Sunsite.Unc.edu FTP site: /Pub/linux/devel/lang/calls.tar.z To get Calls, some older version of the Linux CD-ROM release is also included. Because it is a useful tool, we also introduce here. If you feel useful, you can get a copy from BBS, FTP, or another CD-ROM. Calls calls the GCC's preprocessor to process the given source program file, then output the function call the tree in these files. Note: Install Calls on your system, log in as superuser, perform the following steps: 1. Unzip and Untar files. 2. The subdirectory established after the CD enters Calls Untar. 3. Move the file named calls to the / usr / bin directory. 4. Move the file called calls.1 to directory / usr / man / man1. 5. Delete the / TMP / Calls directory. These steps will put the calls program and its guide page to your system. When Calls prints a tracking result, it gives the file name of the file in the function behind the function after the function: Main [Test.c] If the function is not in the file given to the calls, calls don't know where the call is called, only the name of the function is displayed: PRINTF Calls does not output recursive and static functions. The recursive function is displayed below: FACT <<< Recursive in Factorial.c >>> Static function is like this: Total [static in caverculate.c] As an example, assume that the following programs are treated with Calls: #include Main () { Char my_string [] = "Hello there"; MY_PRINT (my_string); MY_PRINT2 (my_string); } MY_PRINT (Char * String) { Printf ("THE STRING IS% S / N", String); } MY_PRINT2 (Char * String) { Char * string2; Int size, size2, i; SIZE = Strlen (String); Size2 = Size -1; String2 = (char *) Malloc (SIZE 1); For (i = 0; i String2 [Size2 - I] = String [i]; String2 [size] = `/ 0; Printf ("The String Printed Backward IS% S / N", String2); The following output will be produced: 1 main [test.c] 2 my_print [test.c] 3 Printf 4 my_print2 [test.c] 5 strlen 6 malloc 7 Printf Calls has a lot of command line options to set different output formats, please refer to the Calls's guide page for more information on these options. The method is to type Calls -h on the command line. CPROTO CPROTO reads into the C source file and automatically produces prototypes for each function. With CPROTO, you can save you a lot of time to define a function prototype when you write. If you let Cproto processes the following code: #include Main () { Char my_string [] = "Hello there"; MY_PRINT (my_string); MY_PRINT2 (my_string); } MY_PRINT (Char * String) { Printf ("THE STRING IS% S / N", * String); } MY_PRINT2 (Char * String) { Char * string2; Int size, size2, i; SIZE = Strlen (String); Size2 = Size -1; String2 = (char *) Malloc (SIZE 1); For (i = 0; i String2 [Size2 - I] = String [i]; String2 [size] = `/ 0; Printf ("THE STRING Printed Backward IS% S / N", String2); } You will get the following output: / * Test.c * / INT main (void); INT my_print (char * string); INT my_print2 (char * string); This output can be redirected to a defined function prototype. Indent The Indent utility is another programming utility included in Linux. This tool simply produces a beautiful indentation format for your code. Indent also has many options to specify how to format your source code. For more information on these options, see the Indent's guide page, type indent -h on the command line. The following example is the default output of Indent: Run the previous C code before: #include MAIN () { Char my_string [] = "Hello there"; MY_PRINT (my_string); MY_PRINT2 (my_string);} MY_PRINT (Char * String) { Printf ("THE STRING IS% S / N", * String); } MY_PRINT2 (Char * String) { Char * string2; Int size, size2, i; SIZE = Strlen (String); Size2 = Size -1; String2 = (char *) Malloc (SIZE 1); For (i = 0; i String2 [Size2 - I] = String [i]; String2 [size] = `/ 0; Printf ("The String Printed Backward IS% S / N", String2); Code running in Indent: #include Main () { Char my_string [] = "Hello there"; MY_PRINT (my_string); MY_PRINT2 (my_string); } MY_PRINT (Char * String) { Printf ("THE STRING IS% S / N", * String); MY_PRINT2 (Char * String) { Char * string2; Int size, size2, i; SIZE = Strlen (String); Size2 = Size -1; String2 = (char *) Malloc (SIZE 1); For (i = 0; i String2 [Size2 - I] = String [i]; String2 [size] = `/ 0; Printf ("THE STRING Printed Backward IS% S / N", String2); } Indent does not change the substance of the code, but only change the appearance of the code. Make it more readable, which is always a good thing. GPROF GPROF is a program installed in the / usr / bin directory of your Linux system. It allows you to analyze your programs to know which part of the program is performed. Gprof will tell you that each function is called by the number and the percentage of time when performing each function. This information is very useful if you want to improve your program performance. In order to use GPROF on your program, you must add -pg option when compiling. This will cause the program to generate a file called GMON.OUT at each execution. Gprof creates a profiling information with this file. After you run your program and generate the gmon.out file, you can use the following command to obtain an analysis: GPROF The parameter program_name is the name of the program that produces the GMON.out file. Tip: The profiling data generated by GPROF is very large. If you want to check this data, it is best to redirect the output to a file. F2C and P2C F2C and P2C are two source code conversion programs. The F2C converts the FORTRAN code to C code, and P2C converts the PASCAL code to C code. Both programs will be installed when you install GCC. If you have some code written by Fortran or PASCAL, F2C and P2C are very useful to you with C re-write. The C code generated by the two programs is generally not compiled by GCC without modification. If the Fortran or Pascal program to be converted is smaller, you can use F2C or P2C without any options without any options. If the program to be converted is large, if you contain a lot of files, you may have to use some command line options. Use F2C on a Fortran program, enter the following command: F2C my_fortranprog.f Note: The extension of the F2C requiring the converted program is .f or a .f. To replace a PASCAL program as a C program, enter the following command: P2C my_pascalprogram.pas The file names of these two programs generated by C source code are the same as the original file name, but the extension is changed to .f or .pas.