当前位置 博文首页 > Asia-Lee:Linux环境下的C++编程基础

    Asia-Lee:Linux环境下的C++编程基础

    作者:[db:作者] 时间:2021-09-07 16:42

    目录

    一、工具准备

    二、程序的编译及调试

    1、程序的编译及常用命令

    2、gdb调试

    三、Makefile文件基础

    1、Makefile介绍

    2、Makefile编写

    3、make的运行和退出


    一、工具准备

    gcc是GNU的C编译器(GNU C Compiler)

    g++是GNU的C++编译器(GNU C++ Compiler)

    gdb是Linux下常用的调试工具,主要功能如下

    • 启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
    • 可让被调试的程序在你所指定的调置的断点处停住(断点可以是条件表达式)。
    • 当程序被停住时,可以检查此时你的程序中所发生的事。
    • 你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。

    Makefile文件:Makefile是程序编译的规则,makefile记录着整个工程的编译规则(如源文件的编译顺序、依赖关系等),通过make工具进行编译。make根据makefile定义的规则将源代码编译成二进行文件。在跨平台(特别是类Unix系统中)的程序中,一般都会通过makefile来进行编译。

    二、程序的编译及调试

    1、程序的编译及常用命令

    $ g++ main.cpp? ? ?#编译程序,在当前目录自动生成一个a.out的可执行文件

    $ ./a.out? ?? # 执行可执行文件,即运行程序

    $ g++ main.cpp -o test? ? ? ? # 指定自己想要生成的可执行程序的别名 (test)

    $ g++ -c main.cpp? ? ??# 将源代码编译成目标文件(main.o),不进行链接

    $ g++ main.o -o test1($ g++ -o test1 main.o)? ?? #g++接编译后的(*.o)文件进行链接,生成可执行程序 (test1)

    $ ldd test1? ? ? ?#该命令可以看到可执行程序 (test1)所链接的库

    $ g++ -o test1 main.cpp -L /usr/Lib -l /usr/include? ? ? #将依赖的函数库和库路径加入

    • -L 指定连接的动态库或者静态库路径 ;

    • -I(大写i) 指定头文件路径 ,即include文件(也就是包含的*.h头文件)所在的目录;

    • -l(小写L) 指定需要链接的库的名称

    $ gcc -g main.c -o test? ? ??#使用gdp调试C/C++程序, 在编译时,必须要把调试信息加到可执行文件中

    $ g++ -g main.cpp -o test

    注: 编译过程包括预处理、编译,链接 ;linux系统上的编译生成.o文件,windows系统上的编译生成.obj文件 ;linux系统上生成没有后缀的可执行文件,windows系统中生成.exe文件 ; linux系统下的静态函数库的后缀是.a,动态库是.so ; windows系统下的静态函数库的后缀是.lib,动态库是.dll。

    2、gdb调试

    GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。可以用来调试C,C++程序。

    gdp功能及其常用命令

    命令形式功能解释
    gdb -g main.cpp -o test编译代码时的命令,要把调试信息加到可执行文件中
    gdb进入gdb调试命令
    help显示帮助信息,例:help quit,显示quit命令的信息
    q/quit退出GDB调试
    file test加载被调试的可执行程序文件test;或者直接使用gdb ./test进行debug调试命令
    l/list列出文件的内容
    b/break <line number>在某一行设置普通断点,运行到该行即停止,例:b 7
    b/break <line number> if condition在某一行设置条件断点,运行到该行满足条件即停止,例:b 7 if index=2
    b/break <function name>在某一个函数调用处设置断点,运行到函数调用出即停止,例:b getSum
    r/run运行调试的程序(如果程序中没有设置断点,则程序会一直运行到结束或者出现异常结束,如果设置断点,则会在断点处停止)
    d/delete <break number>删除断点编号对应的断点,例:d 1
    clear清空所有的断点信息
    start开始调试
    c/continue继续执行程序直到下一个断点或者程序结束
    n/next逐行调试
    s/step遇到函数时进到函数内部调试
    p/print <value>显示变量的值,即查看变量数据,例:p index

    gdb调试技巧总结下载?

    三、Makefile文件基础

    1、Makefile介绍

    Makefile文件关系到了整个工程的编译规则,它定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

    Makefile带来的好处就是“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

    make是一个命令工具,是一个解释makefile中指令的命令工具, 在终端中输入make命令,会自动搜索当前路径下的makefile或者是Makefile文件 。

    2、Makefile编写

    (1)Makefile示例1及分析

    edit:main.o test.o          #需要生成的目标:生成目标的依赖项
        g++ main.o test.o -o test       #以Tab键开始,具体要执行的命令
    test.o:
        g++ -c test.cpp
    main.o:
        g++ -c main.cpp
    
    clean:
        rm main.o test.o
    • makefile书写规则包含两个部分,一个是依赖关系,一个是生成目标的方法。
    • 我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中(最好使用 “Makefile”这个文件名),然后在该目录下直接输入命令“make”就可以生成执行文件edit。
    • 如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make clean”就可以。
    • 在Makefile中使用“#”字符,表示注释。

    通过示例1看make的工作过程:

    • 首先,输入make命令,make会在当前目录下找名字叫“Makefile”或“makefile”的文件;
    • 如果找到,它会找文件中的第一个目标文件,即“edit”文件,并把这个文件作为最终的目标文件;
    • 如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件;
    • 如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程);
    • 然后再用 .o 文件生成make的终极任务,也就是执行文件edit。

    这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在寻找的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make 就会直接退出,并报错,而对于所定义的命令的错误或是编译不成功,make根本不理。make 只管文件的依赖性。

    (2)Makefile示例2及分析

    #################################################
    # Example for call LTP libraries under UNIX     #
    #################################################
    cc=g++
    ccflags=-O2
    all: cws \
    	pos
    
    cws: cws.cpp
    	${cc} ${ccflags} -o cws cws.cpp -I./ \
    		-I../include/ \
    		-I../thirdparty/boost/include \
    		-L../lib/ -lsegmentor -lboost_regex
    
    pos: pos.cpp
    	${cc} ${ccflags} -o pos pos.cpp -I./ \
    		-I../include/ \
    		-L../lib/ -lpostagger
    
    .PHONY: clean
    
    clean:
        rm cws
        rm pos
    
    • 反斜杠(\)是换行符的意思。这样比较便于Makefile的阅读;
    • -I../include/表示依赖的头文件路径,-L../lib/表示依赖的库路径;
    • -O2:表示编译时使用二级优化
    • makefile中使用变量,比如:cc=g++,makefile中以“$(cc)”的方式来使用这个变量;变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有“:”、“#”、“=”或是空字符(空格、回车等)。变量是大小写敏感的,“foo”、“Foo”和“FOO”是三个不同的变量名。
    • 清空目标文件的规则:为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。只要有“.PHONY : clean ”这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只需“make clean” 即可。

    (3)Makefile编写规则

    • 显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
    • 隐晦规则。由于make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
    • 变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
    • 文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。
    • 注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“#”。

    注:在Makefile中的命令,必须要以[Tab]键开始。

    (4)make工作时执行过程

    • 读入所有的Makefile;
    • 读入被include的其它Makefile;
    • 初始化文件中的变量;
    • 推导隐晦规则,并分析所有规则;
    • 为所有的目标文件创建依赖关系链;
    • 根据依赖关系,决定哪些目标要重新生成;
    • 执行生成命令。

    (5)makefile文件中使用通配符

    我们想定义一系列比较类似的文件,可以使用通配符。make支持三种通配符:“*”,“?”和“[...]”;通配符可以代替一系列的文件,如“*.cpp”表示所有后缀为cpp的文件。一个需要我们注意的是,如果我们的文件名中有通配符,如:“*”,那么可以用转义字符“\”,如“\*”来表示真实的“*”字符。

    (6)Makefile中的-Wall -O2 -Os -g等选项介绍

    • -Wall:选项可以打印出编译时所有的错误或者警告信息。这个选项很容易被遗忘,编译的时候,没有错误或者警告提示,以为自己的程序很完美,其实,里面有可能隐藏着许多陷阱。变量没有初始化,类型不匹配,或者类型转换错误等警告提示需要重点注意,错误就隐藏在这些代码里面。没有使用的变量也需要注意,去掉无用的代码,让整个程序显得干净一点。下次写Makefile的时候,一定加-Wall编译选项。
    • -O0: 表示编译时没有优化。
    • -O1: 表示编译时使用默认优化。
    • -O2: 表示编译时使用二级优化。
    • -O3: 表示编译时使用最高级优化。
    • -Os:相当于-O2.5优化。

    3、make的运行和退出

    (1)make的运行

    直接在命令行下输入make命令,make命令会找当前目录的makefile来执行,一切都是自动的。

    (2)make的退出

    make命令执行后有三个退出码:

    • 0 —— 表示成功执行。
    • 1 —— 如果make运行时出现任何错误,其返回1。
    • 2 —— 如果你使用了make的“-q”选项,并且make使得一些目标不需要更新,那么返回2。

    ?

    cs
    下一篇:没有了