IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> gdb调试工具 -> 正文阅读

[系统运维]gdb调试工具

gdb(The GNU Project Debugger)

linux下的程序调试工具

gdb的安装

执行下列命令,如果没安装,则进行安装;如果安装过,则进行更新
1、Centos下:

sudo yum -y install gdb

2、ubuntu下:

sudo apt-get install gdb

gdb调试

用gcc编译源程序的时候,编译后的可执行文件不会包含源程序代码,如果您打算编译后的程序可以被调试,编译的时候要加 -g 的参数
例如:

gcc -g xxx.c -o xxx
gdb xxx

基本调试命令

命令命令缩写命令说明
breakb设置断点
b 20 表示在第20行设置断点
可以设置多个断点
runr开始运行程序, 程序运行到断点的位置会停下来
如果没有遇到断点,程序一直运行下去
nextn执行当前行语句
如果该语句为函数调用,不会进入函数内部执行
printp显示变量值
p name表示显示变量name的值
p 后面也可以接表达式
continuec继续程序的运行,直到遇到下一个断点
listl查看文件代码
quitq退出gdb环境
set var name=value设置变量的值
假设程序有两个变量:int ii; char name[21];
set var ii=10 把ii的值设置为10;
set var name=“西施” 把name的值设置为"西施",注意,不是strcpy。
set args设置主程序的参数
例如:./xxx a b
(gdb) set args a b
p argc p argv[0] p argv[1]打印
steps执行当前行语句,如果该语句为函数调用,则进入函数,执行该函数的第一条语句
注意,如果函数是库函数或第三方提供的函数,用s也是进不去的,因为没有源代码
如果是您自定义的函数,只要有源码就可以进去。

如果参数里面包括特殊字符,则需要将参数用双引号 “” 括起来
在gdb调试下,可以使用 shell 命令, shell command

segment fault(core dump)段错误(核心已转储)

操作非法地址之后,系统会生成 core 文件
segment fault产生的原因:

  1. 坏指针错误:在指针赋值之前就用它来引用内存
  2. 改写错误:越过数组边界写入数据,在动态分配的内存空间以外写入数据,或改写一些堆管理数据结构
  3. 指针释放引起的错误:释放同一块内存两次,或释放一块未曾使用 malloc 分类的内存,或释放一个无效的指针

程序挂掉的时,系统缺省不会生成 core 文件

  1. gcc -g xxx.c

  2. ./a.out
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLORTUc2-1628954126099)(image/段错误.png)]

  3. ulimit -a 查看系统参数;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WYKu2M7T-1628954126121)(image/ulimit-a.png)]

  4. ulimit -c unlimit 把 core 文件的大小设为无限制;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JxsicZc5-1628954126125)(image/修改core文件大小.png)]

  5. 运行程序,生成 core 文件;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZgkYfNAd-1628954126137)(image/core.png)]

  6. gdb 程序名 core文件名
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OccER9AI-1628954126140)(image/调试.png)]

  7. 输入 bt,可查看函数调用栈
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sbiMBA4l-1628954126142)(image/函数调用栈.png)]

调试正在运行的程序

如果程序进入了死循环,一直运行,那么重新打开一个终端,先查看当前的进程pid

ps -ef | grep a.out
gdb a.out -p pid

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3FsG5hsM-1628954126145)(image/pid.png)]

调试多进程

fork()函数  
#由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是子进程的进程 id  

wait(*status)函数  
//进程一旦调用了wait,就会分析当前进程的某个子进程是否已经退出。如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
//参数status是一个指向int类型的指针。如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,我们就可以设定这个参数为NULL,就象下面这样:
wait(NULL)
//如果成功,wait会返回被收集的子进程的进程ID;如果失败,此时wait返回-1。

exit()函数
//关闭所有文件,终止正在进行的进程
//exit(0)表示正常退出
//exit(1)表示异常退出
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main()
{
   pid_t id = fork();//创建一个子进程
   if(id == 0)
   {
      //id==0,说明这是子进程
      printf("i am child, pid = %d, ppid = %d\n",getpid(),getppid());
      int i;
      for(i = 0;i < 10;i++)
      {
         printf("child i = %d\n",i);
      }
      exit(1);
   }else{
      //id>0 说明这是父进程
      int i;
      sleep(1);
      printf("i am parent, pid = %d, ppid = %d\n",getpid(),getppid());
      for(i = 0;i < 10;i++)
      {
         printf("parent i = %d\n",i);
      }
      if(wait(NULL) != -1)
      {
         printf("wait success\n");
      }
   }
   return 0;
}
follow-fork-mode:
set follow-fork-mode [parent/child] //设置调试进程,默认父进程
show follow-fork-mode   //查看当前调试模式

detach-on-fork:
set detach-on-fork [on/off]   //调试当前进程时,其它进程是运行的还是挂起的,默认是 on 
//挂起表示不显示进程执行内容

info inferiors
//查询正在调试的进程,带 * 表示当前正在调试的进程

inferior <infer number>
//切换调试进程

调试多线程

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>

void* pthread_run1(void* arg)
{
   for(int i = 0; i < 10; i++)
   {
      printf("I am thread1, ID: %ld, %d\n",pthread_self(), i);
      sleep(1);
   }
}
void* pthread_run2(void* arg)
{
   for(int i = 0; i < 10; i++)
   {
      printf("I am thread2, ID: %ld, %d\n",pthread_self(), i);
   sleep(1);
   }
}
int main()
{
   pthread_t tid1;
   pthread_t tid2;
   //创建两个进程
   pthread_create(&tid1, NULL, pthread_run1, NULL);
   pthread_create(&tid2, NULL, pthread_run2, NULL);

   printf("I am main thread\n");
   //等待进程的结束
   pthread_join(tid1, NULL);
   pthread_join(tid2, NULL);
   return 0;
}
gcc -g test_thread.c -lthread
//线程是第三方提供的线程库,编译时要链接第三方库
//-l 表示链接哪个库

info threads //查看线程
thread <ID> //切换线程
set scheduler-locking off|on
thread apply ID1 ID2 command //让一个或多个线程执行GDB命令command
thread apply all command //让若有被调试线程执行GDB命令command
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:58:38  更:2021-08-15 15:59:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 0:55:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码