• linux笔记1常用开发工具


    目前,linux平台上最常用的是C语言,其编译系统是gcc,能够编译用C, C++等语言编写的程序。
    
    一般来说,系统安装后就已经安装和设定好了gcc
    
    在shell的提示符下键入gcc v,屏幕上就会显示出目前正在使用的gcc的版本。
    
    C语言编译过程
    
    C语言程序包括:源文件、头文件、库文件;
    
    在Linux系统中,C/C++程序编译命令是gcc;
    
    当使用gcc时,gcc会完成预处理、编译、汇编和连接;
    前三步生成目标文件,
    连接时把生成的目标文件链接成可执行文件
    
    gcc可以针对不同的源程序文件进行不同处理,文件格式以文件的后缀来识别
    
    预处理阶段
    
    预处理是常规编译之前预先进行的工作,故此得名
    负责读取C语言源文件,对其中以“#”开头的指令(伪指令)和特殊符号进行处理
    
    将“#include”所指出的文件替代该程序行,有两种格式:
    #include <文件名>
     #include “文件名” 
    
    对C语言源程序中的宏名进行宏替换。
    #define EOF -1
    预处理程序将程序中有EOF的部分以-1取代。
    预处理程序对源程序进行“替换”之后,输出的文件就不包含宏定义、文件包含、条件编译等指令,与源文件功能相同,而形式不同。
    
    宏定义:
    1.可以在C程序中:
    #define name value:
    如: #define stuname “Wang”
    
    
    也可以在gcc命令的选项中设置宏定义;
    gcc –D name=definition
    
    第二种方式的优先级高于第一种方式,可以覆盖源文件中的定义
    
    gcc命令的使用
    在Linux系统中,C/C++程序编译命令是gcc,例如
    $ gcc [options] [filenames]
    1.其中filenames为所要编译的程序源文件;
    
    2.执行完成后,生成默认的可执行文件a.out;
    3.[options]部分可以有较多取值
    如:预处理选项、编译选项、优化选项、连接选项,使得gcc命令的功能很多
    
    $ cat hello.c
        
    #include “test1.h”
        
    #define var1 “call for help”
    
       
    main()
       
       {
    
           printf(“display –D variable %s\n”, DOPTION);
    
           printf(“display overwrite var1=%s\n ”, var1);
    
           printf(“hello, everyone!\n”);
    
        }
    
    假设上述程序中,头文件test1.h存放在目录/temp中,且头文件里定义了变量var1,
    下面用gcc命令对上述C程序进行编译,
    $ gcc hello.c
    
    则会提示找不到头文件test1.h,以及DOPTION未定义;
    
    因此,编译的时候要在gcc命令的选项里面,加入头文件test1.h的路径:
    $ gcc –I /temp hello.c
    此时,会提示:变量var1重定义、DOPTION未定义
    
    在gcc命令的选项里加入对DOPTION的宏定义:
    $ gcc –I /temp –D DOPTION=”test” –E hello.c
    -E:只做预处理,比如:宏替换,用参数的取值替代宏名;
    不做编译,将结果显示在标准输出上
    
    替代结果:
    main()
    
       {
    
           printf(“display –D variable %s\n”, “test”);
    
           printf(“display overwrite var1=%s\n ”, “call for help”);
    
           printf(“hello, everyone!\n”);
    
        }
    
    编译完成后,生成默认的可执行文件a.out
    $ a.out
    
           display –D variable test
    
           display overwrite var1=call for help
    
           hello, everyone!
    
    编译阶段
    对预处理之后的输出文件进行词法分析、语法分析,试图找出所有不符合语法规则的部分
    并根据问题给出错误消息,终止编译,或给出警告
    当确定程序符合语法规则后,将其“翻译”为功能等价的中间代码,或汇编代码。
    
    汇编过程
    
    汇编程序(Assembler)把汇编代码翻译成目标机器代码
    包括代码段和数据段等部分,前者包括程序指令,后者存放各种全局或局部变量。
    
    gcc的编译程序选项
    
    选项格式 	          功         能 
    -c 	只生成目标文件,不进行连接。用于对源文件的分别编译 
    -S 	只进行编译,不做汇编,生成汇编代码文件格式,其名与源文件相同,但扩展名为.s 
    -o file 将输出放在文件file中。如果未使用该选项,则可执行文件放在a.out中
    -g 	指示编译程序在目标代码中加入供调试程序gdb使用的附加信息
    -v 	在标准出错输出上显示编译阶段所执行的命令,即编译驱动程序及预处理程序的版本号 
    
    
    $ cat m1.c
    
       #include<stdio.h>
    
       main()
    
       {
    
           int r;
    
           printf(“enter an integer\n”);
    
           scanf(“%d”,&r);
    
           square(r);
    
           return 0;
    
        }
    $ cat m2.c
    
       #include<stdio.h>
    
       int square(int x)
    
       {
    
           printf(“square =%d\n”, x*x);
    
           return (x*x);
    
        }
    若直接编译m1.c文件:gcc m1.c,则会提示:
    
    m1.c文件中的main函数调用的square函数,但没有事先定义和声明。
    因此需要使用-c选项
    
    
    $ gcc –c m1.c
    
    $ gcc –c m2.c
    
    $ gcc m1.o m2.o –o m12
    
    $ m12
    
         enter an integer
    
         6
    
         square=36
    
    
    -c选项表示:
    只生产目标文件(后缀为.o,参见表6.1),而不进行连接,可用于对源文件分别编译。
    
    连接阶段
    
    连接程序(Linker)要解决外部符号访问地址问题
    
    将一个文件中引用的符号(如:变量、函数调用),与该符号在另外一个文件中的定义连接起来,
    最终成为操作系统可以执行的可执行文件。
    
    3  gdb程序调试工具
    程序中的错误可按性质分为三种:
    
    1)编译错误,即语法错误。在编译阶段出现, 如:括号不对称、缺少分号等;
    2)运行错误:运行时才能发现, 如:除数为0,循环终止条件无法达到
    3)逻辑错误:程序可以正常运行,但结果不对。
    
    
    查找程序中的错误,诊断其准确位置,并予以改正,这就是程序调试
    
    Linux系统中包含了调试程序gdb
    它是一个用来调试C和 C++ 程序的调试器;
    gdb可以在程序运行时观察程序的内部结构和内存的使用情况;
    
    gdb 所提供的一些功能如下所示
    运行程序,设置程序运行的参数和环境;
    
    控制程序在指定的条件下停止运行;
    
    当程序停止时,可以检查程序的状态;
    
    动态监视程序中变量的值;
    
    gdb程序调试的对象是可执行文件,而不是程序的源代码文件;
    如果要让产生的可执行文件可以用来调试,需在执行gcc指令编译程序时,
    加上-g参数,指定程序在编译时包含调试信息;
    
    gdb调试程序一般步骤:
    1)$gcc -g test.c -o test
    2)$gdb test
    3)(gdb)run
      系统会给出错误提示
    4)(gdb)backtrace
      显示函数调用时栈的情况
      一般栈顶就是开始出现错误的地方
    5)(gdb)list
      显示源码中错误行上下文5行,共10行
    6)(gdb)break 19 if i=100
      Breakpoint i at 0x8048395:file test.c,line 19
    7)(gdb) run
    8)(gdb)s
    9)(gdb)print i
    
    gdb调试过程中的常用命令
    准备工作:
    为了发挥gdb的全部功能,需要在编译源程序时使用-g选项 :
    
     $ gcc  -g  m1.c  -o m1 
    
    
    启动gdb的方法有以下几种:
    1)直接使用shell命令gdb   $ gdb
    2)以一个可执行程序作为gdb的参数 $ gdb m1
    
    
    显示源程序和数据
    在被调试的源程序中,进行上下文搜索,也可设定搜索路径
    1)显示源文件
    利用list命令可以显示源文件中指定的函数或代码行
    2)模式搜索:在源代码中搜索给定模式的命令
    
    查看运行时数据
    1)print命令 
    一般使用格式是 :print  [/fmt]  exp
    
    当被调试的程序停止时,可以用print命令,查看当前程序中运行的数据。
    如:print i         print i*j
    
    gdb所支持的运算符
     ① { type }adrexp    表示一个数据类型为type、存放地址为adrexp的数据
     ② @ 运算符:
             
    print  array@10   从基地址array开始的10个数组元素值
    print  array[3]@5   从array第三个元素开始的,5个数组元素值
    
     ③ file :: var  (或者 function :: var )
    表示文件file(或者函数function)中变量var的值 
    
    控制程序的执行
    进入gdb后,可以在源程序的某些行上设置断点(breakpoint)
    
    
    程序执行到断点所在行,则暂停执行
    
    此外还有:
    
    观察点(watchpoint):观察某个表达式的值是否发生变化
    
    捕捉点(catchpoint):针对程序运行时出现的事件,如:进程的创建
    
    断点、观察点、捕捉点统称为停止点
    
    1)设置断点:用break命令设置断点:
    
    break  linenum              
    
    break  linenum  if  condition  
    
    break  function              
    
    break  file:linenum
    
    break  file:function         
    
    break  *address                  
    
    break  
    2)显示断点:显示程序中设置了哪些断点
    info  breakpoints  [num]
    
    info  break  [num]
     
    
    维护停止点:清除和停用停止点
    
           delete      clear     disable        enable  
    
    运行程序:设置断点后,用run命令运行程序
    
    程序的单步跟踪
    
    设置断点后,可以让程序一步步地向下执行,用户可以仔细检查运行过程,实行单步跟踪的命令是step和next,
     step  [N]  其中N为步长
     next  [N] 
    
    两者区别是:
        
    后者遇到函数调用时,执行整个函数,即将其作为一条指令对待;
         
    前者进入函数内执行,每次仍然是执行N行语句。
    
    修改变量值:
    
    用户根据需要更改程序运行路线、变量的值,
    如:
    (gdb) print  x=10
    
    (gdb) set variable x=10
    
    跳转执行
    通常,被调试程序是顺序执行的,可以利用jump命令,
    
    在gdb环境中让程序跳转到指定的代码行。
    格式为:
    
    jump  linenum
    
    jump  *addr 
    
    程序维护工具make
    
    软件开发过程中,往往采用结构化的程序设计思想,将一个大型程序分为若干个功能明确的子程序;
    最终的可执行文件依赖于各个目标文件、源文件、库文件等,如果其中某些文件修改了,那么是否需要把所有文件都重新编译、连接一遍呢?
    
    为了减轻系统的编译负担,Linux开发环境提供了程序维护工具:make
    
    
    make的工作机制
    通过使用make工具,程序员只需要定义各文件之间的依赖关系和相关操作
    
    自动检测一个大型程序的哪些部分需要重新编译,然后发出编译命令
    
    基本原理 :
    要使用make命令,必须编写一个叫做makefile的文件,这个文件描述了软件包中文件之间的关系,提供更新每个文件的命令;
    
    一般在一个软件包里,通常是可执行文件靠目标文件(.o后缀)来更新,目标文件靠编译源文件来更新;
    
    makefile写好之后,每次改变了某些源文件,只要执行make命令,所有必要的重新编译将执行。
    
    make程序利用makefile中的数据、每个文件的最后修改时间来确定那个文件需要更新,对于需要更新的文件,根据makefile数据中定义的命令来更新。 
    
    
    makefile文件
    是一个文本形式的数据库文件,其中包含一些规则,告诉make命令需要处理哪些文件,以及如何处理;
    
    
    makefile涉及三方面内容
    目标文件、相依文件和操作命令
    
    makefile文件示例:
    假设:某个正在开发的程序包括prog.c和code.c两个C语言源文件,头文件有prog.h和code.h
    且:
    prog.c使用了prog.h和code.h两个头文件中声明的变量;
    
    最后生成的可执行文件名为test;
    
    则,相应的makefile文件为:
    test:prog.o code.o
           gcc –o test prog.o code.o
     
    prog.o:prog.c prog.h code.h
             gcc –c prog.c
     
    code.o:code.c code.h
    	
             gcc –c code.c
     
    clean:
    
    	rm –f *.o 
    
    
    在检查文件prog.o和code.o的时间戳之前,make会在下面的行中寻找以prog.o和code.o为目标的规则;
    
    在第三行中找到了关于prog.o的规则,该文件的依赖文件是prog.c、prog.h和code.h;
    
    同样,make会在后面的规则行中继续查找这些依赖文件的规则,
    
    如果找不到,则开始检查这些依赖文件的时间戳,
    如果这些文件中任何一个的时间戳比prog.o的新,make将执行“gcc –c prog.c –o prog.o”命令,更新prog.o文件;
    

      

  • 相关阅读:
    LeetCode15 3Sum
    LeetCode10 Regular Expression Matching
    LeetCode20 Valid Parentheses
    LeetCode21 Merge Two Sorted Lists
    LeetCode13 Roman to Integer
    LeetCode12 Integer to Roman
    LeetCode11 Container With Most Water
    LeetCode19 Remove Nth Node From End of List
    LeetCode14 Longest Common Prefix
    LeetCode9 Palindrome Number
  • 原文地址:https://www.cnblogs.com/wust221/p/3074925.html
Copyright © 2020-2023  润新知