Linux C下gdb调试工具简记

1、gdb调试工具
gcc -g -o sum sum.c
gdb ./sum
调试命令:
file –> 指定调试文件
list/l –> 查看原代码(默认10行)
list n –> 列出n附近的10行代码
run/r –> 运行
break/b –> 设置断点 如: b main b 10
info breakpoints/i b –> 查看所有的断点
delete breakpoints <Breakpoint Number>/d b number–> 删除断点
next/n –> 单步运行下一行代码(遇到函数调用不会进入函数内运行)
step/s –> 单步运行下一行代码(遇到函数调用会进入函数内运行)
print/p
set variable 变量名=值
until/u 26 –> 跳到某行
finish –> 跳出函数(finish不能简写成f)
quit/q –> 退出gdb
display /i $pc
同时显示c代码和汇编代码

disassemble 函数名
查看指定函数的反汇编代码

1) 查看寄存器
info registers或者i r
查看寄存器的情况
info all-registers或者i r a
查看所有寄存器的情况
info registers eip或者p $eip
查看指定寄存器

2) 查看内存
(gdb) x /x 0x80040000 # 以16进制显示指定地址处的数据
(gdb) x /s 0x86468700 # 以字符串形式显示指定地址处的数据
(gdb) x /d 0x86468700 # 以十进制形式显示指定地址处的数据
(gdb) x /o 0x86468700 # 以八进制形式显示指定地址处的数据
(gdb) x /t 0x86468700 # 以二进制形式显示指定地址处的数据
(gdb) x /d $ebp-0x8 # 以十进制形式显示寄存器ebp中的值减去0x8后地址处的数据

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

3) 修改寄存器的值
(gdb) set $v0 = 0x004000000
(gdb) set $epc = 0xbfc00000

4) 修改内存的值
(gdb) set {unsigned int}0x8048a51=0x0
2、objdump工具
objdump -xd sum.o
objdump -xd sum
将.o目标文件或可执行文件进行反汇编

Linux C 学习笔记 二

缓冲区

在程序和输出设备间缓冲数据fflush

 

库函数的使用

静态库:编译时刻将库代码链接到应用程序生成文件较大

共享:程序运行时载入共享库代码

动态:程序中语句需要使用时载入库代码

 

静态库的制作

1、模块化编写库模块

fun.c fun.h 就是说把需要实现的模块分开来写,而不是写在main里面

2、编译生成目标文件

fun.o

gcc -c -o obj/fun.o src/fun.c -Iinclude

3、使用目标文件生成静态库文件

libfun.a

ar -rc 库文件名 目标文件名

eg: ar -rc lib/libfun.a obj/fun.o

 

4、将库文件链接到主程序的目标文件中

libfun.a+main.o

gcc -o bin/main obj/main.o -Llib -lfun

-L 库文件目录路径

-l 库文件 去掉lib 和扩展名

共享库

1、模块化编写库模块

fun.c fun.h 就是说把需要实现的模块分开来写,而不是写在main里面

2、编译生成目标文件

fun.o

gcc -c -o obj/fun.o src/fun.c -Iinclude

3、生成共享库文件

libfun.so

gcc -fPCI -shared -o lib/libfun.so obj/fun.o

4、将库文件链接到主程序目标文件

libfun.so + main.o

gcc -o bin/main obj/main.o -Llib -lfun

5、将共享库配置到当前系统中

1)将共享库拷贝到系统默认库路径下

lib/, /usr/lib

(2)配置当前系统的环境变量

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:lib/

当简称相同的时候,扩展名不一样时,优先选择.so文件

例: libfun.so libfun.a共存优先选择.so文件

 

如何批量化的执行编译过程Makefile

批量化执行文件处理过程

desk:wood nail

make up

wood:tree

cut

nail:iron

burn

使用make执行Makefile文件

默认执行名为Makefile的文件

-f 制定执行的文件名 make -f Makefile.shared

 

当你修改了其中之一的文件时,再次执行make时,它会只能比较文件,只执行编译最新的文件

当你就是想要编译一下的话,那可以编写clean:项目

clean:

rm -rf obj/main.o obj/fun.o

rm -rf bin/main

使用make clean执行清理工作

警告提示

-Wall 打开所有类型语法警告 ,建议使用

-Wchar-subscripts 如果数组使用char类型变量作为下标值,则发出警告

警告warnin

编译有可能成功,会生成输出文件

错误error

语法错误,编译失败

1、编译错误一般为语法错误,容易修改

根据编译器的提示修改错误

追踪法

2、运行错误一般为逻辑错误 int *p=100 把指针强制置为100

printf(“%d”,*p);

则会报运行时错误

a、标记法

printf(“message\n”);

b、添加删除法(注释法)

c、调试法

借助调试工具进行调试debug

gdb工具+vi +gcc/g++ =Linux 下三大工具链

在使用GDB调试工具时要多加一个参数 -g

gcc -g -o sum sum.c

gdb ./bin/sum

 

gdb工具

list/l列出代码

run/r执行到结果

break/b 设置断点

info breakpoints/i b 查看所有断点

delete breakpoints db bumbers删除断点

next/n 单步运行不进入行数

step/s 进入函数

print/p 查看变量值

set variable 变量名=

until/u 直接跳到某行

display 跟踪变量的值

 

代码优化

-O1 线程跳转和延迟退栈优化

-O2 包含O1并进行额外的调整工作

-O3 循环展开以及和处理器特性相关的优化

&&&

&& 逻辑与 0为假 非0为真

& 按位与

|| 逻辑或

|按位或

 

 

C 语言数据类型,只有四种数据类型,C语言是强类型语言,必须定义类型

整型

浮点型

指针

聚合类型(数组和结构)

 

整型

字符(char),短整型(short),整型,长整型(long)

char 0~255

singed char -127~127

unsigned char 0~255

char

数据类型与整型的联系

ASCII码表

char ch=’9′

char ch=9;

进制类型

十进制 100

八进制 0100 —-64

十六进制 0x100 —>256

二进制 0b100 —->4

枚举类型

enum

 

溢出问题,造成数据紊乱

正溢出:超过了最大范围

负溢出:小于最低下限

 

a为整数,b为整数 2者皆为溢出

问:如何判断a+b不溢出

if(a>INT_MAX-b)

{

溢出?

}

标识符

变量名

函数名

宏名

Linux C 学习笔记 一

嵌入式Linux C

www 原则:what why how

编译型语言

源代码 –>编译器–>二进制文件

解释型语言

shell html

 

<<C Programing language>>

 

语言关注度排行

c

java

c++

objective -c(oc)

main 函数—>程序的入口

程序一个入口,一个出口(多个位置)

 

main函数的一些写法

main() —不推荐

main(void) —不推荐

void main() —不推荐

int main(void) —标准

int main(int,char**) —没有参数名,不推荐,二级指针

int main(int,char*[]) —不推进啊

int main(int argc,char **argv) —不推荐

int main(int argc,char *argv[]) —标准

int main(int argc,char argv[],char *env[]) –env环境变量

 

argc 代表命令行参数个数,

argv 参数列表

 

文件类型

.c c语言源文件source

*.cpp *.cxx c++语言源文件

.h 头文件header

.o 目标文件object,已经过编译的二进制代码,但未链接

*.so *.a 库文件libraryfor Linux.a问静态库 .so 动态库、共享库

*.dll (for windows)

.png 杂项

.jpg

.ini

 

 

项目结构

src 源文件

include/inc 头文件

obj 目标文件

lib 库文件

bin 二进制可执行文件

 

 

gcc

-o 指定输出文件名

-E 在预处理期完成后就停止编译过程,得到 .i文件

-S 在编译期完成后停止编译过程,*.s

-c 在汇编期完成后停止编译过程,*o

-I 指定头文件的路径

 

多行注释匹配原则

与上一个距离最近且未被匹配的符号进行匹配

多行注释不可嵌套

需要注释多行注释可使用条件编译

条件编译(预处理指令)

#if 0

/*写在里面的都将被删除

#endif

c 语言有两种条件逻辑,一种是0 一种是非0

 

#include <头文件>

#include “头文件”

1C标准库函数的头文件

2、由程序员自定义的头文件

3、第三方的库的头文件

 

<>和“”区别在于在编译的过程中,头文件的搜索路径不同

<> 优先从系统头文件路径开始搜索

“”优先从用户制定的头文件路径开始搜索

 

预处理

gcc -E -o example.i example.c 指到这个预处理期过程就停止,得到的就是

执行的是文本操作,

a.展开include指令 ,把所有包含的头文件都进行引导

b.条件编译 解析#if的内容,将逻辑假内容删除

c.宏展开

#define 定义的宏名都替换成其相应的值

d.删除注释

c语言中定义两个相同的变量,会报错,从定义

 

 

编译阶段

把已经预处理后的代码编译生成汇编代码

gcc -S -o example.s example.i

汇编阶段

编译汇编代码 vi 使用的是asscii格式查看文本,可以使用 bvi安装插件查看二进制代码

gcc -c -o obj/helloword.o src/helloword.c

链接阶段

将目标文件和库文件、其他目标文件进行链接,生成可执行文件

gcc -o bin/helloword obj/helloword.o

 

C语言的算法

有穷性,确切性,输入,输出,可行性

 

-1%256= 255 ==> (-1+256)%256=255

 

printf()函数

%d 有符号十进制整数 int

%c 字符 char ‘a’

%s 字符串 char * “aaaa”

%o 有符号八进制

%x 十六进制

%p 地址指针 0xffffffff

%f 浮点数 float

32位系统—> 寻址空间为32bits —>实际操作只有3Gb

0x0000 0000 0000 0000 0000 0000 0000 0000

…..

0xffffffff ………

 

0x0000 0000

用户空间

0xc000 0000

内核空间

0xffff ffff

 

所有进程运行在内核态

 

库函数的使用

%s/;$/\n{\n}/g 替换全部的;结尾的 然后换行{换行} 替换全部

 

 

执行编译

gcc -c -o obj/fun.o src/fun.c -Iinclude

gcc -c -o obj/main.o src/main.c -Iinclude

-Iinclude 表示-I后面进阶自己写的头文件的目录

执行链接

gcc -o bin/main obj/main.o obj/fun.o