8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

gdb是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。对于一名Linux下工作的c++程序员,gdb是必不可少的工具。

gdb可以做四种主要的任务,从而帮助我们找到程序中的bug:启动程序,指定可能影响其行为的任何内容。

让你的程序在指定条件下停止。

检查当程序停止时发生了什么。

更改程序的内容,以便你可能纠正一个错误的影响后,继续了解另一个错误。

被调试的程序可以用Ada、C、C++、Objective-C、Pascal以及许多其他的语言,其中主要用于C/C++的调试工作。

gdb主要的交互命令:

运行run:简记为r,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。

continue:简记为c,继续执行,到下一个断点处(或运行结束)。

next:简记为n,单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同step的主要区别是,step遇到用户自定义的函数,将步进到函数中去运行,而next则直接调用函数,不会进入到函数体内。

step:简记为s,单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的。

until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。

until+行号:运行至某行,不仅仅用来跳出循环。

finish:运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。

call函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)。

quit:简记为q,退出gdb。

设置断点break n (简写b n):在第n行处设置断点,也可以带上代码路径和代码名称:b OAGUPDATE.cpp:578。

b fn1 if a>b:条件断点设置。

break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button。

delete 断点号n:删除第n个断点。

disable 断点号n:暂停第n个断点。

enable 断点号n:开启第n个断点。

clear 行号n:清除第n行的断点。

info b (info breakpoints):显示当前程序的断点设置情况。

delete breakpoints:清除所有断点。

查看源代码list:简记为l,其作用就是列出程序的源代码,默认每次显示10行。

list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12。

list 函数名:将显示“函数名”所在函数的源代码,如:list main。

list:不带参数,将接着上一次list命令的,输出下边的内容。

打印表达式print 表达式:简记为p,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。

print a:将显示整数a的值。

print ++a:将把a中的值加1,并显示出来。

print name:将显示字符串name的值。

print gdb_test(22):将以整数22作为参数调用gdb_test()函数。

print gdb_test(a):将以变量a作为参数调用gdb_test()函数。

display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如:display a。

watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如:watch a。

whatis:查询变量或函数。

info function:查询函数。

扩展info locals:显示当前堆栈页的所有变量。

查询运行信息where/bt:当前运行的堆栈列表。

bt backtrace:显示当前调用堆栈。

up/down:改变堆栈显示的深度。

set args 参数:指定运行时的参数。

show args:查看设置好的参数。

info program:来查看程序的是否在运行,进程号,被暂停的原因。

分割窗口layout:用于分割窗口,可以一边查看代码,一边测试。

layout src:显示源代码窗口。

layout asm:显示反汇编窗口。

layout regs:显示源代码/反汇编和CPU寄存器窗口。

layout split:显示源代码和反汇编窗口。

Ctrl + L:刷新窗口。

实例:

一个简单的例子:使用一个空指针。

1

2

3

4

5

6

7#includeint main(int argc, char** argv)

{

int *boom = NULL;

printf("hello %d",*boom);

return 0;

}

现在,让我们用符号来编译它,这通过在运行gcc时使用-g标志来完成。

1gcc -g main.c -o main

然后我们运行它,并得到一个很讨厌的段错误:

1

2#./main

[1] 28105 segmentation fault (core dumped) ./main

现在,我们需要找到问题出现在哪里。启动gdb,语法很简单:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18#gdb main

GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git

Copyright (C) 2018 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law. Type "show copying"

and "show warranty" for details.

This GDB was configured as "x86_64-linux-gnu".

Type "show configuration" for configuration details.

For bug reporting instructions, please see:

.

Find the GDB manual and other documentation resources online at:

.

For help, type "help".

Type "apropos word" to search for commands related to "word"...

Registered pretty printers for UE4 classes

Reading symbols from main...done.

(gdb)

接下来只需要在gdb内部运行命令。使用run启动程序

1

2

3

4

5

6

7(gdb) run

Starting program: /home/gjc-2333/code/notes/blog/example/main

Program received signal SIGSEGV, Segmentation fault.

0x0000555555554665 in main (argc=1, argv=0x7fffffffddc8) at main.c:6

6printf("hello %d",*boom);

(gdb)

从上面的信息可以看到,问题出现在第六行,即printf行。

知道问题出现在哪一行,接下来就可以设置断点了。利用break命令可以设置断点,它允许你具体指定断点,或者在自己的函数或有外部库加载的第三方函数指定断点,或者在原代码的特定行指定断点。同时,我们还可以用info命令来检查断点。我们将断点放在main函数中。

1

2

3

4

5

6(gdb) break main

Breakpoint 1 at 0x555555554659: file main.c, line 5.

(gdb) info breakpoint

Num Type Disp Enb Address What

1 breakpoint keep y 0x0000555555554659 in main at main.c:5

breakpoint already hit 1 time

现在我们再次运行代码,当执行到main()函数的时候,执行暂停。

1

2

3

4

5

6

7

8(gdb) run

The program being debugged has been started already.

Start it from the beginning? (y or n) y

Starting program: /home/gjc-2333/code/notes/blog/example/main

Breakpoint 1, main (argc=1, argv=0x7fffffffddc8) at main.c:5

5int *boom = NULL;

(gdb)

接下来逐步执行,使用next命令。

1

2

3

4

5

6

7

8(gdb) next

6printf("hello %d",*boom);

(gdb) next

Program received signal SIGSEGV, Segmentation fault.

0x0000555555554665 in main (argc=1, argv=0x7fffffffddc8) at main.c:6

6printf("hello %d",*boom);

(gdb)

虽然现在知道了程序在第六行崩溃,但是具体什么原因,还是无法知晓。但问题出现的范围相较于一开始模糊的段错误已经精确到了某一行崩溃,当然大部分程序到达这部分的时候,基本都是逻辑错误,需要自己进一步排查到底是什么原因。

以下的内容涉及到汇编,对于队会便不是非常熟悉的人来说,看汇编找bug并不比直接看代码找逻辑错误明智,甚至可能浪费很多时间而最终还是无法了解代码究竟是哪里出了问题。但这并不是说不需要学汇编,能够看懂汇编在许多时候可以帮助我们更快地找到代码的bug。

反汇编

但是,现阶段,代码什么都没有告诉我们,我们也无法直接判断出代码到底发生了什么。如果只看这行代码,似乎没有任何大的问题,或者,我们还无法看到问题的根源。

所以我们在这里使用反汇编命令,它将转储(dump)汇编代码。只需要在gdb中键入disassemble,这将转储你的代码使用的汇编指令。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20(gdb) disassemble

Dump of assembler code for function main:

0x000055555555464a : push %rbp

0x000055555555464b : mov %rsp,%rbp

0x000055555555464e : sub $0x20,%rsp

0x0000555555554652 : mov %edi,-0x14(%rbp)

0x0000555555554655 :mov %rsi,-0x20(%rbp)

0x0000555555554659 :movq $0x0,-0x8(%rbp)

=> 0x0000555555554661 :mov -0x8(%rbp),%rax

0x0000555555554665 :mov (%rax),%eax

0x0000555555554667 :mov %eax,%esi

0x0000555555554669 :lea 0xa4(%rip),%rdi # 0x555555554714

0x0000555555554670 :mov $0x0,%eax

0x0000555555554675 :callq 0x555555554520

0x000055555555467a :mov $0x0,%eax

0x000055555555467f :leaveq

0x0000555555554680 :retq

End of assembler dump.

(gdb)

左边是内存地址。第二列显示内存空间从起始地址开始的增量。第三列显示助记符。第四列包括实际寄存器和值。

小箭头指向我们正在执行的内存地址。在偏移量555555554661H处,我们将移动存储在比本质枕下的8个字节的值到RAX寄存器中。在那只前的一行中,我们将值0移入RBP-8H地址。所以现在RAX寄存器中的值为0。

我们的下一条指令将会导致段错误,正如我们之前使用next命令逐步执行代码时所看到的。

1

20x0000555555554665 :mov (%rax),%eax

0x0000555555554667 :mov %eax,%esi

所以我们需要了解这里为什么会出错。让我们来检查下ESI寄存器,他应该得到这个新的值。我们使用examine或者x命令来做到这一点。

1

2

3

4

5

6

7

8(gdb) x $rax

0x0:Cannot access memory at address 0x0

(gdb) x $eax

0x0:Cannot access memory at address 0x0

(gdb) x $esi

0xffffffffffffddc8:Cannot access memory at address 0xffffffffffffddc8

(gdb)

这里我们得到一个消息:我们不能访问指定的内存地址。现在问题解决了。我们常释放文非法内存地址导致了段错误。

参考资料:

linux gdb#039;查找寄存器地址,【Linux跟踪和调试】gdb相关推荐

  1. linux gdb#039;查找寄存器地址,GDB信息寄存器命令 - 当在gdb运行codeinfo registers/code输出...

    info registers命令以原始格式(十六进制)和自然格式打印寄存器. 自然格式是基于寄存器的类型,在gdb的源代码中的xml文件中声明.例如,i386/64bit-core.xml包含: 可以 ...

  2. 在 Linux 系统中查找 MAC 地址的方法

    参考文章: 多种方法在Linux上找到MAC地址 引言: MAC(Media Access Control)地址是网络设备(如网卡)的唯一标识符,用于在局域网中进行通信.在 Linux 系统中,有几种 ...

  3. linux服务器远程修改mac地址,linux下修改MAC地址问题解决方法

    linux下修改MAC地址问题解决方法 作者:佚名 来源:网络整理 2013-4-17 在linux中,修改MAC地址 # ifdown eth0 # ifconfig eth0 hw ether 1 ...

  4. linux 的手机操作系统下载地址,Linux系统运维之下载Linux操作系统地址

    本文主要向大家介绍了Linux系统运维的下载Linux操作系统地址,通过具体的内容向大家展现,希望对的大家学习Linux运维知识有所帮助. 有很多初次接触Linux的新人都会发问,应该到哪里下载Lin ...

  5. linux版本的qq下载地址,linux版本qq的安装

    tar xzvf linuxqq_v1.0.2_i386.tar.gz cd linuxqq_v1.0.2_i386 ./qq 运行出错解决 1 -bash: ./qq: /lib/ld-linux. ...

  6. 在Linux系统中查找IP地址(六种方式)

    在terminal输入命令 hostname -I 或 ifconfig 或 ip addr 或 ip address 或 ip addr show 或 ip address show

  7. linux 笔记本 显卡驱动下载地址,linux笔记本上安装了双显卡驱动(intel+nvidia)

    为了提高linux图形性能并降低功耗,独特的文章. 我用的系统Fedora 20 Xfce x64,在安装驱动程序,以确保系统是最新的版本号. 最好安装gcc.kernel-devel和其他包.己主动 ...

  8. linux内核态获取ip地址,Linux内核支持动态获取IP地址

    配置选项: NFS: Network File System PNP: Plug-and-Play CONFIG_ROOT_NFS 若想要Linux box通过NFS依赖网络上的其他计算机来mount ...

  9. linux使用grep查找文件内容,Linux中使用grep命令搜索文件名及文件内容的方法

    这篇文章主要介绍了Linux中使用grep命令搜索文件名及文件内容的方法,同时文中还介绍了将匹配结果高亮显示的方法,相当实用,需要的朋友可以参考下 从文件中搜索并显示文件名 当从多个文件中搜索时,默认 ...

最新文章

  1. sq服务启动后又停止_“本地计算机上的SQL SERVER服务启动后又停止了”解决方法...
  2. 个人贷款的条件、流程和注意事项
  3. CLI4 去掉严格模式
  4. 查看mysql 内核_如何查看和更新数据库内核小版本
  5. GDI中的坐标映射问题
  6. scikit-learn一般实例之一:绘制交叉验证预测
  7. java 调用 dll 乱码_java调用c++ dll出现中文乱码
  8. ASP.NET Core缓存静态资源
  9. 通过图书编号查询python_文字版图书管理-python练习
  10. Python(19)-字符串、Unicode字符串
  11. Java RandomAccessFile readUTF()方法及示例
  12. 天猫净饮水行业趋势白皮书2021
  13. 如何在游戏机制中使用AI/剧情脚本----基于LUA
  14. Windows 98 资源管理(转)
  15. 复盘2020:那些崛起的公司
  16. Python 结合bat批处理文件 实现密码保管箱
  17. mt6573芯片资料汇总
  18. SAP ABAP搜狗输入法注释删除注释快捷键设置(未解决)
  19. office Excel操作
  20. csapp2e 家庭作业 4.52 4.53

热门文章

  1. CentOS下与Apache连接的PHP多版本共存方案实现详解
  2. 使用SSH+SFTP操作终端全解析,告别XShell
  3. Mac python3.x使用HTMLTestRunner.py
  4. 洛谷 1658 购物
  5. JAVA中this和super用法
  6. Python学习-字符编码的理解
  7. XML 文档(0, 0)中有错误。缺少根元素。
  8. TypeForwardedTo Attribute ---- 类型传递
  9. 机器人差速驱动方式(Differential Drive)
  10. git apply、git am打补丁.diff 和 .patch