实验室的课题以及平时程序代码的编写,在Windows环境下,基本上都是通过IDE来编写调试程序,但是在linux环境下通过g++
编译器和vim
编辑器来编写程序,在体验上更加geek
,通过在linux系统下工作学习,真正的达到了心无旁骛,专心写代码,谨以此作个简单的记录。接下来的时间,将算法方面的学习转移到linux上,熟悉linux环境下g++
编程和gdb
调试以及了解makefile
的编写。
g++
流程
linux下的可执行文件并不像Windows系统以.exe
文件后缀标志,只需要分配x
(可执行)权限即可sudo chmod u+x excutefile
源文件-->预处理-->编译-->汇编-->链接-->可执行文件
关于详细流程可参考:C/C++程序编译流程(预处理->编译->汇编->链接)
#include <iostream>
#define MAX 100
int main()
{
std::cout<<MAX<<std::endl; //output the max
return 0;
}
1.预处理,生成.i的文件[预处理器cpp]
g++ -E test.cpp > test.i
通过执行上面的命令,输出预处理后的文件,如下面部分可以看到主要做宏的替换、注释的消除以及找到相关库文件。在该步骤不会进行语法错误检查。
song@song-pc:~$ cat test.i |less
# 1 "test.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.cpp"
# 1 "/usr/include/c++/5/iostream" 1 3
# 36 "/usr/include/c++/5/iostream" 3
# 37 "/usr/include/c++/5/iostream" 3
# 1 "/usr/include/x86_64-linux-gnu/c++/5/bits/c++config.h" 1 3
# 194 "/usr/include/x86_64-linux-gnu/c++/5/bits/c++config.h" 3
/////////////////////省略了部分内容//////////////////////////////
# 2 "test.cpp" 2
# 4 "test.cpp"
int main()
{
std::cout<<100<<std::endl;
return 0;
}
2.将预处理的文件转换成汇编语言,生成文件.s[编译器egcs]
g++ -S test.cpp
3.汇编变为目标代码,生成.O文件
g++ -C test.cpp
在该步骤进行词法和语法的检查,比如花括号不匹配,行末没有分号,关键字错误等。
4.连接目标代码,生成可执行程序
g++ test.o -L F:\include\iostream
将.o
文件与所需的库文件链接整合成可执行文件。
模块化程序
上面讲述的是单个cpp文件,但是开发中采用的是模块化开发,需要多个源文件共同组成编译单元,最终形成可执行程序。
创建以下三个文件:
-rw-rw-r-- 1 song song 100 9月 18 16:34 hello.cpp
-rw-rw-r-- 1 song song 32 9月 18 16:32 hello.h
-rw-rw-r-- 1 song song 75 9月 18 16:36 main.cpp
各个源文件内容为:
hello.h
song@song-pc:~/test$ cat hello.h
extern void print();
hello.cpp
song@song-pc:~/test$ cat hello.cpp
#include <iostream>
using namespace std;
void print()
{
cout<<"hello world"<<endl;
}
main.cpp
song@song-pc:~/test$ cat main.cpp
#include "hello.h"
void print();
int main()
{
print();
return 0;
}
最后生成执行命令
song@song-pc:~/test$ g++ hello.cpp main.cpp -o hello
当然以上命令也可以分拆为3步命令
song@song-pc:~/test$ g++ -c hello.cpp -o hello.o
song@song-pc:~/test$ g++ -c main.cpp -o main.o
song@song-pc:~/test$ g++ hello.o main.o -o hello
gdb
当程序编译完成,但是可能无法正常运行,或者是生成的结果不是需要的,这样的情况就需要对程序进行调试跟踪代码块的执行。gdb
是GNU
开发组织发布的一个强大的UNIX/Linux
下的程序调试工具。主要有以下功能:
- 启动程序,可以按照用户自定义的要求运行程序。
- 可让被调试的程序在用户所指定的调试的断点处停住 (断点可以是条件表达式)。
- 当程序停住时,可以检查此时程序中所发生的事。
- 动态地改变程序的执行环境。
从功能上来看,gdb和一般的调试工具区别不大,可能习惯了图形化的调试工具暂时还不大习惯,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。
song@song-pc:~/test$ g++ -g test.cpp -o test //使用gdb调试
song@song-pc:~/test$ gdb test //启动gdb
(gdb) l //注意这里是小写的L,相当于list命令,列出源码
2 using namespace std;
3
4 int sum(int n)
5 {
6 int result=0;
7 for(int i=0;i<n;++i)
8 {
9 result+=i;
10 }
11 return result;
(gdb) l
12 }
13
14 int main(void)
15 {
16 int result=0;
17 result=sum(10);
18 cout<<result<<endl;
19 }
20
(gdb) break 4 //在源程序第4行,设置断点
Breakpoint 1 at 0x40081d: file test.cpp, line 4.
(gdb) break 15 //在源程序第15行,设置断点
Breakpoint 2 at 0x40084c: file test.cpp, line 15.
(gdb) info break //显示断点信息
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040081d in sum(int) at test.cpp:4
2 breakpoint keep y 0x000000000040084c in main() at test.cpp:15
(gdb) r //运行程序,run命令简写
Starting program: /home/song/test/test
Breakpoint 2, main () at test.cpp:16 //在断点处停住
16 int result=0;
(gdb) n //单条语句执行,next命令简写
17 result=sum(10);
(gdb) n
Breakpoint 1, sum (n=10) at test.cpp:6
6 int result=0;
(gdb) n
7 for(int i=0;i<n;++i)
(gdb) n
9 result+=i;
(gdb) n
7 for(int i=0;i<n;++i)
(gdb) p result //打印变量result的值,print命令简写
$1 = 0
(gdb) p i
$2 = 0
(gdb) bt //查看函数堆栈
#0 sum (n=10) at test.cpp:7
#1 0x000000000040085d in main () at test.cpp:17
(gdb) finish
Run till exit from #0 sum (n=10) at test.cpp:7
0x000000000040085d in main () at test.cpp:17
17 result=sum(10);
Value returned is $3 = 45
(gdb) c //继续运行程序,continue命令简写。
Continuing.
45 //程序输出
[Inferior 1 (process 10695) exited normally]
(gdb) q //退出gdb
gdb主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数即可。
$ gcc -g hello.c -o hello
$ g++ -g hello.cpp -o hello
如果没有-g,将看不见程序的函数名和变量名,代替它们的全是运行时的内存地址。当用-g把调试信息加入,并成功编译目标代码以后,看看如何用gdb来调试。 启动gdb的方法有以下几种:
- gdb
program也就是执行文件,一般在当前目录下。 - gdb
core 用gdb同时调试一个运行程序和core文件,core是程序非法执行后,core dump后产生的文件。 - gdb
如果程序是一个服务程序,那么可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试它。program应该在PATH环境变量中搜索得到。 gdb启动时,可以加上一些gdb的启动开关,详细的开关可以用gdb -help查看。下面只列举一些比较常用的参数: -symbols -s 从指定文件中读取符号表。 -se file 从指定文件中读取符号表信息,并把它用在可执行文件中。 -core -c 调试时core dump的core文件。 -directory -d 加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。
(未完) 下面还有makefile部分
参考资料
- gcc/g++基本命令简介http://www.cnblogs.com/cryinstall/archive/2011/09/27/2280824.html
- g++基本用法http://www.cnblogs.com/cryinstall/archive/2011/09/27/2280824.html