[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.pswp.cn/news/382689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/382689.shtml
英文地址,請注明出處:http://en.pswp.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…