[Linux]gdb调试多进程多线程例程

gdb相信学linux的同学已经比较熟悉了吧,它是linux下代码调试工具。我们在写c语言,c++的代码时经常会用到,它有一些常用的调试命令:

run(r):运行程序,如果有断点在下一个断点处停止
start:开始执行程序,停在main函数第一条语句前
list(l):列出源码,接着上次的位置向下列,每次列10行
list+行号:列出第几行附近的10行源码
list+函数名:列出某个函数名附近10行源码
print(p):显示变量或表达式值
where:哪里出错
whatis:查看变量的类型
info(i):查看当前栈帧局部变量的值
backtrace(bt):查看各级函数调用及参数
frame(f):帧编号,选择栈帧
break:设置断点
break 行号
break 函数名
break 文件名:行号
break 文件名:函数名
delete 1-3: 删除1到3断点
info break:显示断点信息
set variable var = value: 修改变量的值
continue(c): 从断点后继续执行
finish:运行到当前函数返回为止,然后停下来
return [value]:停止执行当前函数,将value返回给调用者;
step(s):执行下一步,step将进入函数,执行函数内每条语句;
next(n):执行下一个语句,不进入函数;
enter键:重复执行最后一条命令;

在我们学过信号之后,我又遇到一个问题就是关于core dumped的问题。我们举个栗子说明一下吧~

#include<stdio.h>int main()
{int a = 10;a/=0;return 0;
}

我们看上面的这段代码,在代码编译的角度来看,显然它的除数为0了,会出错。那是一个什么样的错呢。

运行结果:

这里写图片描述

出现了core dumped,这里core dumped称为核心转储。当一个进程由于发生异常终止时,可以选择把用户空间内存储的数据全部保存到磁盘上,文件名通常为core,因此称为core dump。一般情况下,异常终止是因为代码有bug,如非法访问内存导致的段错误,刚刚的错误就属于段错误,浮点数异常。事后可以用调试器检查core文件来查清错误原因,这又被称为事后调试。默认是不允许产生core⽂文件的,因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。

比如上述程序,我们也生成了一个core文件。

这里写图片描述

这里需要注意的是,有些同学可能说为什么自己的代码运行后生成不了core文件,原因是:你使用命令ulimit -a检测一下你的core文件允许的大小。

这里写图片描述

上边的core文件显示的是0.说明你不能生成core文件,这里需要改一下core文件的大小,我们改成1024。使用命令ulimit -c 1024

这里写图片描述

这时,就可以生成core文件了。

这里写图片描述

下面我们来使用gdb来调试一下:

这里写图片描述

gdb调试多进程程序

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>int main()
{pid_t id = fork();int i = 0;if(id == 0){while(1){printf("I am child! i = %d\n",i++);sleep(1);}}else{while(1){printf("hello world!I am parent! i = %d\n",i);sleep(1);}}return 0;
}

我们介绍一些在多进程中新增的一些调试信息:

show follow-fork-mode:查看当前的fork进程,默认为父进程,如果想设置为子进程,则只需命令:set follow-fork-mode child即可

这里写图片描述

show detach-on-fork:显示当前调试哪个进程。默认为on,只调试父子进程中的一个。如果为off,则表示调试父子两个进程。set detach-on-fork off来设置。

这里写图片描述

info inferiors:显示gdb调试的所有进程。inferior [进程编号]:可以切换到特定的inferiors进行调试。其中*代表正在调试的进程。

这里写图片描述

maint info program-spaces:显示当前gdb管理的地址空间数目。

这里写图片描述

detach inferior [进程编号]:detach掉某一进程的编号,此时进程Description部分为NULL

这里写图片描述

kill inferior [进程编号]:杀死当前的fork。比如当前为父进程,则运行时只剩下子进程,当你下次运行的时候会恢复。当前进程为null,且指向kill的进程。

这里写图片描述

remove-inferior [进程编号]:删除某一个inferior。如果该inferior正在运行,则不能删除,因此删除之前必须先killdetach掉。

这里写图片描述

show schedule-multiple:默认为on。显示所有的执行状态的情况。为on表示所有的inferior都可以执行。为off只是当前的inferior执行

这里写图片描述

set print inferior-event on/off:用来打开和关闭inferior状态的提示信息

这里写图片描述

gdb调试多线程

#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>#define SIZE 64
int ring[SIZE];
sem_t blank_sem,data_sem;
void *consume(void* arg)
{int i = 0;while(1){sem_wait(&data_sem);int data = ring[i++];sem_post(&blank_sem);i %= SIZE;printf("consume is %d\n",data);sleep(3);}
}void *product(void *arg)
{int data = 0;int i = 0;while(1){sem_wait(&blank_sem);ring[i++] = data;sem_post(&data_sem);i %= SIZE;printf("product is : %d\n",data++);//  sleep(1);}
}int main()
{sem_init(&blank_sem,0,SIZE);sem_init(&data_sem,0,0);pthread_t c,p;pthread_create(&c,NULL,consume,NULL);pthread_create(&p,NULL,product,NULL);pthread_join(c,NULL);pthread_join(p,NULL);sem_destroy(&blank_sem);sem_destroy(&data_sem);return 0;
}

这里写图片描述

这里写图片描述

thread apply ID command :让ID线程执行命令command
thread apply all command :让所有线程执行命令command
info threads:显示当前可调试的所有线程,gdb为每一个线程分配一个ID号。*表示正在调试的线程。thread [线程ID]:切换到当前要调试的线程ID。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382689.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gdb调试常用命令速查(段错误调试)

编译程序时需要加上-g&#xff0c;之后才能用gdb进行调试&#xff1a;gcc -g main.c -o main gdb中命令&#xff1a; 回车键&#xff1a;重复上一命令 &#xff08;gdb&#xff09;help&#xff1a;查看命令帮助&#xff0c;具体命令查询在gdb中输入help 命令,简写h &…

C语言字符串 小记

#include "stdafx.h" #include <iostream> #include <string.h> using namespace std;int _tmain(int argc, _TCHAR* argv[]) {char str1[] "12345"; // ""括起来的字符串 会在末尾增加 \0 cout << sizeof(str1) << en…

[Linux]守护进程(精灵进程)

一、守护进程是什么 守护进程是生存期很长的一种进程&#xff0c;可以说它是7*24小时工作的。&#xff08;什么是7*24&#xff0c;一周7天&#xff0c;每天24小时&#xff0c;这不就是一年365天一直在工作嘛&#xff0c;还搞的这么诙谐&#xff0c;哈哈&#xff09;。它们常常…

linux命令行界面下ctrl 常用组合键速查表

Ctrlz 暂停正在运行的程序 Ctrll 清屏 Ctrld 结束输入或退出shell Ctrla 切换到命令行开始 Ctrle 切换到命令行末尾 Ctrlu 删除光标前内容 Ctrlk 删除光标后内容 Ctrlxu 撤销操作

[Linux]运输层的端口

既然提到端口&#xff0c;我们就来分析一下为什么要使用端口的缘由吧。我们首先要知道的是&#xff0c;运输层有复用和分用的功能。应用层所有的应用进程都可以通过运输层再传送到IP层&#xff0c;这就是复用。运输层从IP层收到数据后必须交付到指明的应用进程&#xff0c;这就…

浅谈shell中的clear命令实现

NAME(名称) clear - 清除终端屏幕 SYNOPSIS(总览) clear DESCRIPTION(描述) clear可以在允许的情况下清屏. 它会在环境变量中查找终端的类型, 然后到terminfo数据库中找出清屏的方法. 《man手册》 #include <stdio.h>int clear_main(int argc, char **argv) {/* Th…

C++ 对引用的理解

引用可以看做是数据的一个别名&#xff0c;通过这个别名和原来的名字都能够找到这份数据引用必须在定义的同时初始化&#xff0c;并且以后也要从一而终&#xff0c;不能再引用其它数据&#xff0c;这有点类似于常量&#xff08;const 变量&#xff09;。引用变量 里面 实际存储…

[Linux]ARP协议

概念&#xff1a; 1. ARP协议(地址解析协议):由IP地址转换为MAC地址的协议。IP地址&#xff1a;网络号主机号。MAC地址&#xff1a;数据链路层的物理地址&#xff08;硬件地址&#xff09;。IP协议使用了ARP协议&#xff0c;因此被划归为网络层&#xff0c;但其用途是从网络层…

Makefile使用及多文件gdb 调试

文件内容 [koulocalhost makefile]$ cat 1.c #include "3.h" int main() {key_t key ftok(".",1);printf("%d\n",add(1,2));return 0; }[koulocalhost makefile]$ cat 2.c #include "3.h" int add(int a, int b) {return a b; } [k…

C++ 对引用的理解2

1.指针就是数据或代码在内存中的地址&#xff0c;指针变量指向的就是内存中的数据或代码。这里有一个关键词需要强调&#xff0c;就是内存&#xff0c;指针只能指向内存&#xff0c;不能指向寄存器或者硬盘&#xff0c;因为寄存器和硬盘没法寻址。 2.其实 C 代码中的大部分内容…

Ubuntu各版本主要差异

Ubuntu各版本主要差异 (重定向自Ubuntu &#xff0c; kubuntu与xubuntu的差别 ) Ubuntu官方考虑到使用者的不同需求&#xff0c;提供各种不同的发行版。这几种发行版本的差别在于桌面环境和预设安装的软体不同&#xff0c;但套件库是采用一样的&#xff0c;所以您当然可以在安…

[Linux]CRC校验

CRC(Cyclic Redundancy Check),循环冗余校验码&#xff0c;是数据通信领域中最常用的一种差错校验码&#xff0c;其特征是信息字段和校验字段的长度可以任意选定。 CRC校验步骤&#xff1a; CRC分为两部分&#xff0c;前部分为信息码&#xff0c;后部分为校验码&#xff1b;设…

visual studio 2015 配置好qt5后, 第一次运行出现 无法打开源文件“QtWidgets/QApplication”和无法运行rc.exe的解决方案

无法打开源文件“QtWidgets/QApplication” a.在工程中右击项目&#xff0c;点击属性。 b.选择VC目录->包含目录 c.选择Qt安装目录中的头文件包含目录&#xff0c;一般为Qt版本号/版本号/编译器名/include 比如&#xff1a;E:\Qt\Qt5.6.3\5.6.3\msvc2015\include 在C\C>附…

怎么在vs中查看一个数组的所有元素

在监视窗口&#xff0c;我们想要查看所有的数组元素。 这个时候 int arr[] {1,2,3} arr只显示1 正确的方法 arr&#xff0c;10

[Linux]NAT和代理服务器

1. NAT&#xff1a;&#xff08;Network Address Translation&#xff09;是网络地址转换。 我们有这样一种场景&#xff0c;在专用网内部的一些主机本来已经分配到了本地IP地址&#xff0c;但现在又想和因特网上的主机通信&#xff0c;我们可以设法再申请一些全球IP地址&…

使用 C++的第三方库 jsoncpp的步骤以及出现的问题

Jsoncpp 是一个json解析库 下载地址为&#xff1a; http://sourceforge.net/projects/jsoncpp/ 方法一&#xff1a;使用Jsoncpp生成的lib文件 解压上面下载的Jsoncpp文件&#xff0c;在jsoncpp-src-0.5.0/makefiles/vs71目录里找到jsoncpp.sln&#xff0c;用VS2008版本编译&am…

常用的友元重载运算符OSTREAM

对<<运算符重载&#xff0c;让他能和cout一起显示对象内容。 显示值可以使用show()&#xff0c;但是使用cout<<更方便。 ostream类对该运算符进行了重载&#xff0c;将其转换成输出工具。 cout就是一个ostream的对象&#xff0c;他可以自动识别所有的c基本类型。…

python字符串系列

1.find方法用于在长串中查找子串&#xff0c;返回子串中最左位置的下标&#xff0c;如果没找到&#xff0c;则返回-1 2.join方法用于在队列中添加元素 3.lower返回字符串的小写字母版 4.replace返回字符串中所有匹配项均被替换之后得到字符串 5.split将字符串分割成序列 6.stri…

C++ wstring 与 string 之间的相互转换.

方式一&#xff1a;调用Windows API #include <Windows.h> //将string转换成wstring wstring string2wstring(string str) { wstring result; //获取缓冲区大小&#xff0c;并申请空间&#xff0c;缓冲区大小按字符计算 int len MultiByteToWideChar(CP_ACP, 0,…

linux网络编程Internet Socket地址,套接字,和函数

文章内容节选《linux/UNIX 系统网络编程》 Internet domain socket地址有两种&#xff1a;IPv4 IPv6 IPv4被存储在结构体中&#xff0c; 该结构体在 netinet/in.h 中进行定义 cd usr/include/netinet/in.h struct in_addr {in_addr_t s_addr; //32位IPv4地址 }struct so…