GCC GDB调试总结(jyy操作系统学习笔记)
文章目录
1.gcc编译文件
在含 .c 目标文件的目录终端下输入:
gcc -g xx.c -o xx
对于C程序来说,需要在编译时加上-g参数,保留调试信息,否则不能使用GDB进行调试。
然后可以发现在此目录下生成了一个名为 xx 的可执行文件。
2. 启动 gdb 调试
在上节的终端里继续输入 gdb + 上节生成的要调试程序的可执行文件名:
gdb xx
GDB常用调试命令
设置断点:
break 1 #在第一行设置断点
运行:
run
单步执行下一条语句:
s
显示源代码调试窗口:
layout src
看栈帧上面变量的值:
info frame
打印调试变量
p 变量名
p stk[0]
开始调试:
start
切换到汇编代码视角:
layout asm
打印进程信息
info proc mappings
GCC 常用命令
宏展开
gcc -E xx.c
例如:
在vim 里面直接编译
编译
:!gcc %
输出
:!./a.out`
touch
编译运行
对gcc输出的结果排序:
gcc stack.c -lpthread && ./a.out |sort -nk 6 #n z指的是排序的时候按照数字排列,k指的是第几列,6是第六列
使用管道c和python显示数码管
./a.out| python3 seven-seg.py
python:
import fileinput
TEMPLATE = '''
\033[2J\033[1;1f
AAAAAAAAA
FF BB
FF BB
FF BB
FF BB
GGGGGGGGGG
EE CC
EE CC
EE CC
EE CC
DDDDDDDDD
'''
BLOCK = {
0: '\033[37m░\033[0m', # STFW: ANSI Escape Code
1: '\033[31m█\033[0m',
}
VARS = 'ABCDEFG'
for v in VARS:
globals()[v] = 0
stdin = fileinput.input()
while True:
#
exec(stdin.readline())
pic = TEMPLATE
for v in VARS:
pic = pic.replace(v, BLOCK[globals()[v]]) # 'A' -> BLOCK[A], ...
print(pic)
解读:
在命令行下能产生五颜六色的字体和图案,只需要加上一些颜色代码
颜色的控制通过ESC字符(\033)加”[“加颜色代码加”m”实现。ESC的ASCII码是十进制的27,八进制的033(\033)。
设置闪烁颜色:
BLOCK = {
0: '\033[37m░\033[0m', # STFW: ANSI Escape Code
1: '\033[31m█\033[0m',
}
字色 背景 颜色
30 40 黑色
31 41 紅色
32 42 綠色
33 43 黃色
34 44 藍色
35 45 紫紅色
36 46 青藍色
37 47 白色
exec
exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec可以执行更复杂的 Python 代码。
例如:
exec ‘print “Hello World”’
终端显示:Hello World
汉诺塔程序状态机
void hanoi(int n, char from, char to, char via) {
if (n == 1) printf("%c -> %c\n", from, to);
else {
hanoi(n - 1, from, via, to);
hanoi(1, from, to, via);
hanoi(n - 1, via, to, from);
}
return;
}
/* 实现这个算法可以简单分为三个步骤:
(1) 把n-1个盘子由A 移到 B;
(2) 把第n个盘子由 A移到 C;
(3) 把n-1个盘子由B 移到 C;
从这里入手,在加上上面数学问题解法的分析,我们不难发现,移到的步数必定为奇数步:
(1)中间的一步是把最大的一个盘子由A移到C上去;
(2)中间一步之上可以看成把A上n-1个盘子通过借助辅助塔(C塔)移到了B上,
(3)中间一步之下可以看成把B上n-1个盘子通过借助辅助塔(A塔)移到了C上;*/
模拟
//C语言状态机
//状态 = stack frame 的列表 (每个 frame 有 PC) + 全局变量
typedef struct {
int pc, n;
char from, to, via;
} Frame;
#define call(...) ({ *(++top) = (Frame) { .pc = 0, __VA_ARGS__ }; })
#define ret() ({ top--; })
#define goto(loc) ({ f->pc = (loc) - 1; })
void hanoi(int n, char from, char to, char via) {
//数组名:代表的是该数组最开始的一个元素的地址。
Frame stk[64], *top = stk - 1;//函数调用-》创建一个新的栈帧,top指针一开始指向栈底的前一个位置
call(n, from, to, via);//函数调用 = push frame (frame.PC = 入口)
for (Frame *f; (f = top) >= stk; f->pc++) {
switch (f->pc) {
case 0: if (f->n == 1) { printf("%c -> %c\n", f->from, f->to); goto(4); } break;
case 1: call(f->n - 1, f->from, f->via, f->to); break;
case 2: call( 1, f->from, f->to, f->via); break;
case 3: call(f->n - 1, f->via, f->to, f->from); break;
case 4: ret(); break;//函数返回 = pop frame
default: assert(0);
}
}
}
解读
Strace
查看系统调用
gcc -g hellow.c && ./a.out
strace ./a.out
查看编译器编译过程