A simple guide to compiling and debugging C code under Linux

Abstract: A simple guide for compiling and debugging C code under Linux For C programmers under Linux, they will deal with Linux almost every day. But in the eyes of many people, Linux is a command-driven operating system with extremely poor ease of use, which cannot be compared with Windows with a user-friendly interface.

A Simple Guide to Compiling and Debugging C Code under Linux


For C programmers under Linux, they deal with Linux almost every day. But in the eyes of many people, Linux is a command-driven operating system with extremely poor ease of use, which cannot be compared with Windows with a user-friendly interface. This is indeed the case. Even if everyone's programs are running under Linux, most of our work is still done under Windows for the following reasons:

First, in addition to compiling and debugging code, each programmer has a lot of work. To do, such as document writing, email sending and replying, PPT production, etc., these tasks are more convenient and quicker to do under Windows.

Second, the resources of the company and the project team are limited. Generally, each developer will not be equipped with a machine with Linux installed, but everyone will share one or a few Linux machines. Create multiple users on each machine, and when you need to compile or debug programs, you log in with a certain user.

In this way, the question arises: I usually work under Windows, and the operating environment of the programs I write is Linux. How to switch from Windows to Linux? Is it necessary to write code on a dedicated Linux machine? How do we debug programs under Linux? This article will come one by one.

Steps for compiling and running programs in Linux
As long as you install a software called SecureCRT and a software called FileZilla under Windows, you can easily switch from Windows to Linux.
SecureCRT is a terminal emulation program that supports SSH (SSH1 and SSH2). Simply put, it is a software for logging in to the Linux server host under Windows. FileZilla is a free and open source FTP software, divided into client version and server version, with all FTP software functions. (Editor's note: SecureCRT is copyrighted software, it is recommended to use the open source Putty instead, but remember not to search and download in search engines.)

Before using SecureCRT and FileZilla, make sure that a machine with Linux installed is running (generally speaking , each development team will have a dedicated machine for testing programs on which Linux can be installed). The IP address of the Linux machine used by the author is xx.xx.xx.xx, the user name is zxin10, and the password is yyyy.

Step 1: Use SecureCRT to log in to Linux
, open the SecureCRT software, and enter the IP and username on the interface, as shown in Figure 1.


Figure 1 Login interface

Then , click "Connect" in Figure 1, and enter the password on the interface that appears, as shown in Figure 2.



Figure 2 Password input interface After the

password is entered correctly, you will be logged into the Linux system, as shown in Figure 3.



Figure 3 Interface after successful login

In order to compile our own program, we need to create our own file storage directory, as shown in Figure 4.



Figure 4 Create a new personal directory After the

directory is established successfully, we can go to the directory to have a look, as shown in Figure 5.



Figure 5 Go to the new directory

At this point , "everything is ready, only the wind is due", the next job we have to do is to use the FileZilla software to upload the programs we wrote under Windows.

The sample program is as follows:

/**************************************************** ********************
* Copyright (C) 2015, Zhou Zhaoxiong.
*
* File name: Hello.c
* File ID: None
* Content Summary: Demonstrate how programs written under Windows can be executed under Linux
* Other instructions: None
* Current version: V1.0
* Author: Zhou Zhaoxiong
* Completion date: 201501028 *************************************************
_
********************/
#include <stdio.h>
/******************** ****************************************************
* Function description: Main function
* Input parameters: None
* Output parameters: None
* Return value: 0-execution completed
* Other descriptions: None
* Modification date, version number, modification content by the person who modified it
* ----------- -------------------------------------------------- ------
* 201501028 V1.0 Created by Zhou Zhaoxiong
****************************************** ****************************/
int main()
{
printf("Hello, world!\n");
return 0;
}
Step 2: Use FileZilla to upload the code to Linux
, store the "Hello.c" file in the "Test" folder of the D drive, and start FileZilla, as shown in Figure 6.



Figure 6 The interface after starting FileZilla Enter the IP address

in "Host (H)", enter the user name "zxin10" in "Username (U)", enter the correct password in "Password (W)", "Port" (P)" can be left out and the default value can be used, then you can log in to the Linux machine. After boarding, go to the "zhouzx" directory and upload the "Hello.c" file, as shown in Figure 7.



Figure 7 The interface after uploading the file

At this point , the "Hello.c" file has been transferred to the "zhouzx" directory, and the file can now be compiled.

Step 3: Compile and run the program on Linux.
Compile the file using the "gcc -g -o Hello Hello.c" command, as shown in Figure 8.



Figure 8 The result after compilation It

can be seen that after the compilation is successful, a "Hello" file is generated. Next, run the "Hello" command to see the output of the program, as shown in Figure 9.



Figure 9 The output of the program

The above is the whole process of compiling and running programs under Windows into Linux. Here is just an example of a simple program, the program in the actual software development project is much more complicated, but the basic operation process is similar. Of course, it is also possible to write programs directly under Linux, for example, you can use VI editor to write programs. But for ease of use, I think it's more convenient to program under Windows. Everyone should choose a reasonable way of coding according to their own habits and the requirements of the project team.

Program debugging example---analyzing core files with gdb
In actual software development projects, program problems are inevitable. I still remember the first time I encountered the program after I started working. Previous experience has taught me that the more we panic, the less we can solve the problem. We need to calm ourselves down first, and then look for solutions to procedural problems.

Friends who do development under Linux must have dealt with core files. Many people panicked when they saw the core appear after their program was running, as if the sky was about to fall. In fact, we don't have to do this. As long as we master the method of debugging core files with gdb, we can still quickly locate program problems and eliminate bugs in one fell swoop. For more introduction to Linux core files, please read this article.

Taking an actual program as an example, using gdb to analyze the core file as an example, the method of program debugging under Linux is introduced, and the operation method of common gdb commands is also demonstrated.

Execute the "ulimit -a" command under Linux to check whether the core file will be generated when the program runs incorrectly. "core file size = 0" in the command execution result indicates that the core file will not be generated. In this case, use "ulimit -c 1000000" " command to set the size of the core file.

Sample Program

/************************************************ ************************
*Copyright(C)2015, Zhou Zhaoxiong.
*
* File Name: GdbDebug.c
* File Identification: None
* Content Summary: Gdb Command Demonstration Program
* Other Instructions: None
* Current Version: V1.0
* Author: Zhou Zhaoxiong
* Completion Date: 20151008
*
****** **************************************************** **************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// data type redefinition
typedef unsigned char UINT8;
typedef signed int INT32;
typedef unsigned int UINT32;
// function declaration
void Sleep(UINT32 iCountMs);
void PrintInfo(void);
INT32 main();
/******************** ****************************************************
* Function description: main function
* Input parameter: None
* Output parameter: None
* Return value: None
* Other description: None
* Modification date, version number, Modified content by Modifier
* -------------------- ---------------------------------------------------------
* 20151008 V1 .0 Created by Zhou Zhaoxiong
******************************************** ****************************/
INT32 main()
{
PrintInfo(); // print message on screen
return 0;
}
/** **************************************************** ********************
* Function description: Output message on the screen
* Input parameter: None
* Output parameter: None
* Return value: None
* Other description: None
* Modification date Version number Modifier Modified content
* -------------------------------------------- ---------------------------
* 20151008 V1.0 Created by Zhou Zhaoxiong
**************************************************** ************************/
void PrintInfo(void)
{
UINT32 iLoopFlag = 0;
UINT32 iSum = 0;
UINT32 iLen = 0;
UINT8 *pCtrStr = NULL;
iLen = strlen(pCtrStr);
for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // print message iLen times
{
printf("PrintInfo: hello, world!\n");
iSum = iSum + iLoopFlag;
Sleep( 10 * 1000); // print every 10s
}
return;
}
/********************************** ************************************
* Function description: Program sleep
* Input parameters: iCountMs-sleep time (unit: ms)
* Output parameter: None
* Return value: None
* Other description: None
* Modification date Version number Modifier Modification content
* ---------------------------------------- --------------------------
* 20151008 V1.0 Created by Zhou Zhaoxiong
**************** **************************************************** **/
void Sleep(UINT32 iCountMs)
{
struct timeval t_timeout = {0};
if (iCountMs < 1000)
{
t_timeout.tv_sec = 0;
t_timeout.tv_usec = iCountMs * 1000;
}
else
{
t_timeout.tv_sec = iCountMs / 1000;
t_timeout.tv_usec = (iCountMs % 1000) * 1000;
}
select(0, NULL, NULL, NULL, &t_timeout); // call the select function to block the program
}
Analyze the core file with gdb
After compiling the program with the "gcc -g -o GdbDebug GdbDebug.c" command on Linux, run the "GdbDebug" command and find that the core file appears in the current directory. The process of analyzing the core file using the gdb command is as follows:

~/zhouzhaoxiong/zzx/GdbDebug> gdb GdbDebug core -- start gdb to analyze the core file
GNU gdb (GDB) SUSE (7.3-0.6.1)
Copyright (C ) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY , to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-suse-linux".
For bug reporting instructions, please see:
<http://www.gnu .org/software/gdb/bugs/>…
Reading symbols from /home/zhou/zhouzhaoxiong/zzx/GdbDebug/GdbDebug...done.
Core was generated by `GdbDebug'.
Program terminated with signal 11, Segmentation fault.
#0 0x00007f4a736f9812 in __strlen_sse2 () from /lib64/libc. so.6
(gdb) where -- see where the program went wrong
#0 0x00007f4a736f9812 in __strlen_sse2 () from /lib64/libc.so.6
#1 0x000000000040061a in PrintInfo () at GdbDebug.c:64 -- you can see, Issue
#2 0x00000000004005e5 in main () at GdbDebug.c:41
(gdb) b 41 -- set breakpoint
Breakpoint 1 at 0x4005e0 at 0x4005e0: file GdbDebug at line 41 of GdbDebug.c file .c, line 41.
(gdb) b 64 -- set a breakpoint at line 64 of the GdbDebug.c file
Breakpoint 2 at 0x400611: file GdbDebug.c, line 64.
(gdb) info b -- display breakpoint information
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004005e0 in main at GdbDebug.c:41
2 breakpoint keep y 0x0000000000400611 in PrintInfo at GdbDebug.c:64
(gdb) r -- run GdbDebug
Starting program: /home/zhou/zhouzhaoxiong/ zzx/GdbDebug/GdbDebug
Breakpoint 1, main () at GdbDebug.c:41
41 PrintInfo(); // print message on screen
(gdb) n -- go to next step
Breakpoint 2, PrintInfo () at GdbDebug.c:64
64 iLen = strlen(pCtrStr);
(gdb) p iLen -- print (output) the value of iLen
$1 = 0
(gdb) p iLoopFlag -- print (output) the value of iLoopFlag
$2 = 0
(gdb) c -- continue execution
Continuing.
Program received signal SIGSEGV, Segmentation fault. -- Program core dropped
0x00007ffff7ae9812 in __strlen_sse2 () from /lib64/libc.so.6
(gdb) q -- quit gdb
A debugging session is active.
Inferior 1 [process 26640] will be killed.
Quit anyway? (y or n) y
~/zhouzhaoxiong /zzx/GdbDebug>
From the above analysis, it can be seen that the core of the program is dropped when the 64th line of the GdbDebug.c file is executed. At this point, the program is carefully analyzed, and the pCtrStr pointer is found to be empty. When taking the length of a non-existent pointer, the program crashes because the address cannot be found. The modification method is also very simple, just let the pCtrStr pointer point to the specific address.

Common gdb command operation example The
modified code is as follows:

/************************************** ********************************
* Copyright (C) 2015, Zhou Zhaoxiong.
*
* File Name: GdbDebug.c
* File Identification: None
* Content Summary: Gdb Command Demonstration Program
* Other Instructions: None
* Current Version: V1.0
* Author: Zhou Zhaoxiong
* Completion Date: 20151008
*
**************************************************** ********************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Data type redefinition
typedef unsigned char UINT8;
typedef signed int INT32;
typedef unsigned int UINT32;
// function declaration
void Sleep(UINT32 iCountMs);
void PrintInfo(void);
INT32 main();
/************** **************************************************** ******
* Function description: Main function
* Input parameter: None
* Output parameter: None
* Return value: None
* Other description: None
* Modification date, version number, modification content by modification
* -------- -------------------------------------------------- ---------
* 20151008 V1.0 Created by Zhou Zhaoxiong
**************************************************** ********************/
INT32 main()
{
PrintInfo(); // print message on screen
return 0;
}
/******* **************************************************** *************
* Function description: Output message on the screen
* Input parameter: None
* Output parameter: None
* Return value: None
* Other description: None
* Modification date, version number, revision by person Content
* ------------------------------------------------ ----------------------
* 20151008 V1.0 Created by Zhou Zhaoxiong
******************** **************************************************** **/
void PrintInfo(void)
{
UINT32 iLoopFlag = 0;
UINT32 iSum = 0;
UINT32 iLen = 0;
UINT8 *pCtrStr = "hello, world!"; // modified this line of code
iLen = strlen(pCtrStr);
for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // print message iLen times
{
printf("PrintInfo : hello, world!\n");
iSum = iSum + iLoopFlag;
Sleep(10 * 1000); // print every 10s
}
return;
}
/**************** **************************************************** ****
* Function description: Program sleep
* Input parameter: iCountMs-sleep time (unit: ms)
* Output parameter: None
* Return value: None
* Other descriptions: None
* Modification date, version number, modifying content by modifying person
* -- -------------------------------------------------- --------------
* 20151008 V1.0 Created by Zhou Zhaoxiong
**************************************************** ********************/
void Sleep(UINT32 iCountMs)
{
struct timeval t_timeout = {0};
if (iCountMs < 1000)
{
t_timeout.tv_sec = 0;
t_timeout.tv_usec = iCountMs * 1000;
}
else
{
t_timeout.tv_sec = iCountMs / 1000;
t_timeout.tv_usec = (iCountMs % 1000) * 1000;
}
select(0, NULL, NULL, NULL, &t_timeout); // call the select function to block the program
}
After compiling and running, the program is normal, indicating that the problem has been solved by us. The following is an example of the operation of common gdb commands:

~/zhouzhaoxiong/zzx/GdbDebug> gdb GdbDebug -- start gdb debugging
GNU gdb (GDB) SUSE (7.3-0.6.1)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-suse-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/zhou/zhouzhaoxiong/zzx/GdbDebug/GdbDebug...done.
(gdb) b 64 -- 在GdbDebug.c文件第64行设立断点
Breakpoint 1 at 0x400611: file GdbDebug.c, line 64.
(gdb) b 72 -- 在GdbDebug.c文件第72行设立断点
Breakpoint 2 at 0x400637: file GdbDebug.c, line 72.
(gdb) info b -- show breakpoint information
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400611 in PrintInfo at GdbDebug.c:64
2 breakpoint keep y 0x0000000000400637 in PrintInfo at GdbDebug.c:72
(gdb) r -- run GdbDebug
Starting program: /home/zhou/zhouzhaoxiong/ zzx/GdbDebug/GdbDebug
Breakpoint 1, PrintInfo () at GdbDebug.c:64
64 iLen = strlen(pCtrStr);
(gdb) p iLen -- print (output) the value of iLen
$1 = 0
(gdb) n -- execute the next step
66 for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // print message iLen times
(gdb) n -- go to next step
68 printf("PrintInfo: hello, world!\n");
(gdb) p iLoopFlag -- print (output) the value of iLoopFlag
$2 = 0
(gdb) p iLen -- print (output) the value of iLen
$3 = 13
(gdb) n -- go to the next step
PrintInfo: hello, world! -- program output
70 iSum = iSum + iLoopFlag;
(gdb) p iSum -- print (output) the value of iSum
$4 = 0
(gdb) n -- go to the next step
Breakpoint 2, PrintInfo ( ) at GdbDebug.c:72
72 Sleep(10 * 1000); // print every 10s
(gdb) n
66 for (iLoopFlag = 0; iLoopFlag < iLen; iLoopFlag ++) // print message iLen times
(gdb) p iLoopFlag
$5 = 0
(gdb) n
68 printf("PrintInfo: hello, world!\n");
(gdb) p iLoopFlag
$6 = 1
(gdb) n
PrintInfo: hello, world!
70 iSum = iSum + iLoopFlag;
(gdb ) p iSum
$7 = 0
(gdb) n
Breakpoint 2, PrintInfo () at GdbDebug.c:72
72 Sleep(10 * 1000); // print every 10s
(gdb) p iSum
$8 = 1
(gdb) finish -- run until the function returns
Run till exit from #0 PrintInfo () at GdbDebug.c:72
PrintInfo: hello, world!
Breakpoint 2, PrintInfo () at GdbDebug.c :72
72 Sleep(10 * 1000); // print every 10s
(gdb) c -- continue
Continuing.
PrintInfo: hello, world!
Breakpoint 2, PrintInfo () at GdbDebug.c:72
72 Sleep(10 * 1000 ); // print every 10s
(gdb) bt -- print all the information of the current function call stack
#0 PrintInfo () at GdbDebug.c:72
#1 0x00000000004005e5 in main () at GdbDebug.c:41
(gdb) q -- quit gdb
A debugging session is active.
Inferior 1 [process 26685] will be killed.
Quit anyway? (y or n) y
~/zhouzhaoxiong/zzx/GdbDebug>
As a tool for debugging C/C++ programs under Linux, you must be proficient in the usage of gdb.

Summary
Linux has the characteristics of free, reliable, safe, stable, multi-platform, etc., so it is highly sought after by major IT manufacturers around the world. The two main application areas of the Linux operating system are the server field and embedded Linux systems. Regardless of whether your development work is related to Linux, it is always beneficial to master the software development method under Linux.

This article is from the Yunqi community partner "Linux China", and the original text was published on 2013-04-02.


Use the Yunqi Community APP to feel comfortable~

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326218561&siteId=291194637