zoukankan      html  css  js  c++  java
  • 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文件;
    

      

  • 相关阅读:
    P1495 曹冲养猪
    luoguP4281[AHOI2008]紧急集合 / 聚会
    NOIP1997 代数表达式
    luogu P3709大爷的字符串题
    luoguP3912 素数个数
    POJ 1065 Wooden Sticks
    POJ 1063 Flip and Shift
    POJ 1062 昂贵的聘礼
    POJ 1003 Hangover
    POJ 1001 Exponentiation
  • 原文地址:https://www.cnblogs.com/wust221/p/3074925.html
Copyright © 2011-2022 走看看