Linux下开发环境(gcc/g++/makefile/gdb)

先决条件

 

gcc       这是c语言的编译器

   从前,我写了一个Linux多线程到程序Main.c,使用gcc -g Main.c -lpthread -o Main编译,就出现来未安装gcc的提示,我按照提示输入来几个y,然后就把gcc装好了。但是,其实,在Red Hat Enterprise Linux 6上,默认已经安装好gcc,可以编译C语言程序了。

 
gcc-c++      扩展为c++编译器

    This package adds C++ support to the GNU C compiler. It includes support for most of the current C++ specification, including templates and exception handling. It does not include the standard C++ library.

 

libstdc++-v3     The GNU Standard C++ Library v3

    libstdc++-v3 is developed and released as part of GCC, separate snapshots are no longer made available. The libstdc++-v3 sources are included with the GCC sources and can be downloaded from the GCC FTP area or from any of the GCC mirror sites.

 

 

一、gcc与g++编译流程

预处理preprocessing --> 编译compilation --> 汇编assembly --> 链接linking

举例:

[hadoop@sam1 testGCC]$ cat hello.c

 

Cpp代码   收藏代码
  1. #include<stdio.h>  
  2. int main(){  
  3.     printf("in C");  
  4.     return 0;  
  5. }  

 

 

 

(0)一步到位的编译

 

[hadoop@sam1 testGCC]$ ls

hello.c

[hadoop@sam1 testGCC]$ gcc hello.c -o hello

[hadoop@sam1 testGCC]$ ./hello

in C

 

可以使用-O选项告诉GCC对源代码进行基本优化,使程序执行更快,可以替换使用如下命令:

gcc hello.c -o hello -O0          //没有优化

gcc hello.c -o hello -O1          //缺省,主要进行跳转和延迟退栈两种优化

gcc hello.c -o hello -O2          //除了完成-O1 的优化之外,还进行一些额外的指令调整工作

gcc hello.c -o hello -O3          //除了完成-O2 的优化之外,还进行包括循环展开和其他一些与处理特性相关的优化工作

 

 

(1)预处理:源文件hello.c --> 预处理文件hello.i。只激活预处理,不生成文件,需要把它重定向到一个输出文件(预处理器的输出默认被送到标准输出,而非文件中)。

[hadoop@sam1 testGCC]$ ls

hello.c

[hadoop@sam1 testGCC]$ gcc -E hello.c -o hello.i

 

注:

hello.c后缀为c表示:  

         C source code which must be preprocessed.

 

-E  Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.

     Input files which don't require preprocessing are ignored.

 

(2)编译预处理文件hello.i --> 汇编文件hello.s。激活预处理,编译,把文件编译成汇编代码。

 

[hadoop@sam1 testGCC]$ ls

hello.c  hello.i

[hadoop@sam1 testGCC]$ gcc -S hello.i -o hello.s

 

注:

hello.s:

Assembler code. 经过编译后产生了汇编代码

长这个样子:

 

汇编代码   收藏代码
  1.     .file   "hello.c"  
  2.     .section    .rodata  
  3. .LC0:  
  4.     .string "in C"  
  5.     .text  
  6. .globl main  
  7.     .type   main, @function  
  8. main:  
  9.     pushl   %ebp  
  10.     movl    %esp, %ebp  
  11.     andl    $-16, %esp  
  12.     subl    $16, %esp  
  13.     movl    $.LC0, %eax  
  14.     movl    %eax, (%esp)  
  15.     call    printf  
  16.     movl    $0, %eax  
  17.     leave  
  18.     ret  
  19.     .size   main, .-main  
  20.     .ident  "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"  
  21.     .section    .note.GNU-stack,"",@progbits  

  

-S  Stop after the stage of compilation proper; do not assemble.  The output is in the form of an assembler code file for each non-assembler input file specified.

     By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s.

 

(3)汇编汇编文件hello.s --> .o的汇编文件。激活预处理,编译和汇编,把程序做成obj文件。

 

[hadoop@sam1 testGCC]$ ls

hello.c  hello.i  hello.s

[hadoop@sam1 testGCC]$ gcc -c hello.s -o hello.o

 

注:

-c  Compile or assemble the source files, but do not link.  The linking stage simply is not done.  The ultimate output is in the form of an object file for each source file.

     By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.

     Unrecognized input files, not requiring compilation or assembly, are ignored.

 

(4)链接:.o的汇编文件 --> 最终的可执行文件hello。

[hadoop@sam1 testGCC]$ ls

hello.c  hello.i  hello.o  hello.s

[hadoop@sam1 testGCC]$ gcc hello.o -o hello

[hadoop@sam1 testGCC]$ ./hello

in C

 

注:

以上几个参数实际上指定编译在哪个stage退出,不在乎开始指定的文件是什么形式

-E                      截止到预编译完成。

-S                      截止到产生汇编文件。

-c                       截止到产生目标文件,不链接。

不带参数          截止到最终产生链接好的可执行文件。

 

另外,gcc -g 这个参数让编译器在目标文件中加上了调试信息,具体表现为ELF格式目标文件中多出了很多debug段,通过readelf -S ***.o查看,多出了诸如如下的这些调试段:

  [27] .debug_aranges    PROGBITS        00000000 0006e4 000020 00      0   0  1

  [28] .debug_pubnames   PROGBITS        00000000 000704 00004f 00      0   0  1

  [29] .debug_info       PROGBITS        00000000 000753 0000cb 00      0   0  1

  [30] .debug_abbrev     PROGBITS        00000000 00081e 00008d 00      0   0  1

  [31] .debug_line       PROGBITS        00000000 0008ab 000046 00      0   0  1

  [32] .debug_frame      PROGBITS        00000000 0008f4 000054 00      0   0  4

  [33] .debug_str        PROGBITS        00000000 000948 000095 01  MS  0   0  1

 

 

二、一个简单工程的编译——makefile(3 个.cpp 文件,2 个.h 文件)

 

main.cpp

Cpp代码   收藏代码
  1. #include<iostream>  
  2. #include "printf1.h"  
  3. #include "printf2.h"  
  4. int main(){  
  5.     printf1();  
  6.     printf2();  
  7. }  

 

 

printf1.h

Cpp代码   收藏代码
  1. void printf1();  

 

 

printf1.cpp

Cpp代码   收藏代码
  1. #include <iostream>  
  2. #include "printf1.h"  
  3. using namespace std;  
  4.   
  5. void printf1(){  
  6.     cout<<"printf1"<<endl;  
  7. }  

 

 

printf2.h

Cpp代码   收藏代码
  1. void printf2();  

 

 

printf2.cpp

Cpp代码   收藏代码
  1. #include <iostream>  
  2. #include "printf2.h"  
  3. using namespace std;  
  4.   
  5. void printf2(){  
  6.     cout<<"printf2"<<endl;  
  7. }  

 

 

常规编译:

Shell代码   收藏代码
  1. [hadoop@sam1 testGCC]$ ls  
  2. main.cpp  printf1.cpp  printf1.h  printf2.cpp  printf2.h  
  3. [hadoop@sam1 testGCC]$ g++ -c printf1.cpp                   ==> 截止到生成(未链接的)目标文件printf1.o  
  4. [hadoop@sam1 testGCC]$ g++ -c printf2.cpp                   ==> 截止到生成(未链接的)目标文件printf2.o  
  5. [hadoop@sam1 testGCC]$ g++ -c main.cpp                     ==> 截止到生成(未链接的)目标文件main.o  
  6. [hadoop@sam1 testGCC]$ ls  
  7. main.cpp  printf1.cpp  printf1.o    printf2.h  
  8. main.o    printf1.h    printf2.cpp  printf2.o  
  9. [hadoop@sam1 testGCC]$ g++ printf1.o printf2.o main.o -o out       ==>将3个obj文件链接到一个可执行文件上  
  10. [hadoop@sam1 testGCC]$ ./out  
  11. printf1  
  12. printf2  

 

makefile编译:

 

Shell代码   收藏代码
  1. [hadoop@sam1 testGCC]$ ls  
  2. main.cpp  printf1.cpp  printf1.h  printf2.cpp  printf2.h  
  3. [hadoop@sam1 testGCC]$ vim makefile  
  4. ==>见下面makefile文件内容  
  5. [hadoop@sam1 testGCC]$ make  
  6. g++ -c main.cpp             #默认生成main.o  
  7. g++ -c printf1.cpp  
  8. g++ -c printf2.cpp  
  9. g++ main.o printf1.o printf2.o -o out  
  10. [hadoop@sam1 testGCC]$ ls  
  11. main.cpp  makefile  printf1.cpp  printf1.o    printf2.h  
  12. main.o    out       printf1.h    printf2.cpp  printf2.o  
  13. [hadoop@sam1 testGCC]$ ./out  
  14. printf1  
  15. printf2  
  16. [hadoop@sam1 testGCC]$ make clean  
  17. rm -rf *.o out  
  18. [hadoop@sam1 testGCC]$ ls  
  19. main.cpp  makefile  printf1.cpp  printf1.h  printf2.cpp  printf2.h  

 makefile文件:

 

Makefile代码   收藏代码
  1. out:    main.o printf1.o printf2.o      #生成out需要依赖的文件  
  2.     g++ main.o printf1.o printf2.o -o out  
  3. main.o: main.cpp printf1.h printf2.h        #生成main.o需要依赖的文件  
  4.     g++ -c main.cpp             #默认生成main.o  
  5. printf1.o:  printf1.h printf1.cpp  
  6.     g++ -c printf1.cpp  
  7. printf2.o:  printf2.h printf2.cpp  
  8.     g++ -c printf2.cpp  
  9.   
  10. clean:  
  11.     rm -rf *.o out  

 

三、用gdb调试

资料:使用 GDB 调试 Linux 软件,David SeagerCICS/390 开发部,IBM Hursley:http://www.ibm.com/developerworks/cn/linux/sdk/gdb/

资料:LINUX GDB调试实例: http://blog.csdn.net/wangjiannuaa/article/details/6584750

另见本博客《(第一章 1)通用双向链表》(系统程序员-成长计划)

 

下面一个例子说明如何用gdb查看 “缓冲区溢出程序”的运行时堆栈情形——

 

C代码   收藏代码
  1. #include<stdio.h>  
  2. voidwhy_here(void){  
  3. printf("whyuhere?!\n");  
  4. _exit(0);  
  5. }  
  6. intmain(intargc,char*argv[]){  
  7. intbuff[1];  
  8. buff[2]=(int)why_here;  
  9. return0;  
  10. }  

 

 #gcc -g buf.c -o buf

 

启动gdb调试buf

 

在程序开始处设置断点(Sam:这里实际上只设置了一个断点,因为定义变量不会在指令序列中出现)

 

程序跑起来(直到遇到断点 )

 

查看main函数栈信息

 

如果遇到函数:

       单步跳入是step

       单步跳过是next

 

 非常好的文档:

http://www.seas.upenn.edu/cets/answers/gcc.html

http://baike.baidu.com/link?url=uU1zNRtDxA6rGdGQWqsjlM_0q8M_0iGbQD43Z9DbPr9e3dVFE4vSWcebSuwIWpis

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值