1、gcc的使用以及编译原理
(1) 编译过程
例如hello.c程序:
#include<stdio.h>
Int main(void)
{
printf(“hello world!\n”);
return 0;
}
a. 预处理:编译器将代码中的stdio.h的代码编译进来,用户使用-E选项进行查
看;
gcc -E hello.c -o hello.i
b. 编译:gcc首先检查语法的规范性以及是否有语法错误等,以确定代码实际要
做的工作,检查无误后,gcc把代码编译成汇编语言。
Gcc -S hello.i -o hello.s
c. 汇编:把编译生成的.s文件转换成目标文件。
gcc -c hello.s -o hello.o
d. 链接:链接库函数,并生成可执行文件;
gcc hello.o -o hello
(2) 常用编译命令
法一: gcc -c hello.c
gcc -o hello hello.o (链接生成hello可执行文件)
法二: gcc -o hello hello.c (常用)
法三: gcc hello.c (一般不用)
(3) objdump readelf
查看目标文件的结构和内容:objdump -h *.o
查看目标文件的更多信息:objdump -x
查看ELF文件断的内容以十六进制打印:objdump -s
查看段的内容包含指令的段反汇编:objdump -d
2、 gdb调试
(1) 调试对象:Debug版本下的可执行文件(默认是生成relese版本)。
(2) 调试过程:
a. 首先就要生成debug版本:gcc -o main *.c -g
b. 先显示代码:l ; list filename.c : num(行数) 显示指定文件的代码
c. 将断点添加到linenum行:b linenum
将断点添加到funname函数有效行:bu funname
b linenum / funname if条件:条件断点(循环都归时调用)
d. 断点信息查看:info b
e. 删除断点:d bpnum
将断点设置为无效:disable bpnum
将指定断点设置为有效:enable bpnum
(3) 调试常用的命令
r:运行程序到第一个断点处;
s:进入函数运行(将要被调用的函数运行);
finish:退出函数运行;
n:执行下一行;
c:执行到下一个断点处;
q:退出调试;
p valname:查看变量值;
display valname:监视变量值;
undisplay displaynum:取消监视;
p &valname:查看变量地址;
x /nfb addr:查看变量地址对应的内存存储情况;
P arr:显示数组所有元素的值;
P *ptr@len:通过指向数组的指针显示数组元素;
P S_val:查看结构体变量的值;
P S_val.valname:显示结构体变量某一个成员变量的值;
bt:显示函数调用栈;
ptype val:显示变量类型;
(4) 多进程调试
(gdb) set follow -fork -mode mode
注:mode:parent/child即选择调试父进程还是子进程;
未被选择的进程会直接执行结束。
(5) 多线程调试
info threads:查看线程信息;
thread id:调试目标id指定的线程;
set scheduler -locking off|on|step;
off:不锁定任何线程;
on:只有当前被调试的线程继续执行;
step:在单步执行的时候,只有当前线程会执行;
3、 makefile文件:自动化编译,一旦写好makefile文件只需要一个make命令,整个
工程完成自动编译。
(1) 命名:makefile 或者 Makefile
(2) 编辑makefile文件:
举例一个工程下有四个.c文件:main.c my_sub.c my_add.c my_max.c
exe : main.o my_sub.o my_add.o my_max.o
(tab)gcc -o exe main.o my_add.o my_sub.o my_max.o
main.o : main.c
(tab)gcc -c main.c
my_add.o : my_add.c
(tab)gcc -c my_add.c
my_sub.o : my_sub.c
(tab)gcc -c my_sub.c
my_max.o : my_max.c
(tab)gcc -c my_max.c