摘要:臭蟲(chóng)中文常稱為缺陷。與相對(duì)應(yīng),人們將發(fā)現(xiàn)并加以糾正的過(guò)程叫做中文稱作調(diào)試,意即捉蟲(chóng)子或殺蟲(chóng)子。于是,霍珀詼諧的把程序故障統(tǒng)稱為臭蟲(chóng),把排除程序故障叫,而這奇怪的稱呼,后來(lái)成為計(jì)算機(jī)領(lǐng)域的專業(yè)行話。
各位小伙伴們大家好,我是澤奀( ̄o ̄) . 相信大家在編寫(xiě)C程序中會(huì)遇到很多代碼的Bug.所以本篇博客就帶大家如何調(diào)試C的技巧,這樣在遇到有錯(cuò)誤的代碼,也不必驚慌,只需調(diào)試下,Bug就再也不會(huì)存在了哈哈哈~隔。?
?目錄
bug:Bug的原意:可以稱之為“臭蟲(chóng)",現(xiàn)在指代的是漏洞,就是在安全系統(tǒng)上出現(xiàn)缺陷,攻擊者可以對(duì)未授權(quán)的情況下進(jìn)行攻擊,Bug(計(jì)算機(jī)漏洞) 可以形容在各個(gè)領(lǐng)域范圍之內(nèi)所出現(xiàn)的漏洞。
由來(lái):第一代的計(jì)算機(jī)是由許多龐大且昂貴的真空管組成,并利用大量的電力來(lái)使真空管發(fā)光。可能正是由于計(jì)算機(jī)運(yùn)行產(chǎn)生的光和熱,引得一只小蟲(chóng)子(Bug)鉆進(jìn)了一支真空管內(nèi),導(dǎo)致整個(gè)計(jì)算機(jī)無(wú)法正常工作。研究人員費(fèi)了半天時(shí)間,總算發(fā)現(xiàn)原因所在,把這只小蟲(chóng)子從真空管中取出后,計(jì)算機(jī)又恢復(fù)正常。后來(lái),Bug這個(gè)名詞就沿用下來(lái),用來(lái)表示電腦系統(tǒng)或程序中隱藏的錯(cuò)誤、缺陷、漏洞等問(wèn)題。
1945年,計(jì)算機(jī)還是由機(jī)械式繼電器和真空管驅(qū)動(dòng)的,機(jī)器有房間那么大。體現(xiàn)當(dāng)時(shí)技術(shù)水平的MarkⅡ,是由哈佛大學(xué)制造的一個(gè)龐然大物。當(dāng)技術(shù)人員正在進(jìn)行不整機(jī)運(yùn)行時(shí),它突然停止了工作。他們爬上去找原因,發(fā)現(xiàn)這臺(tái)巨大的計(jì)算機(jī)內(nèi)部一組繼電器的觸點(diǎn)之間有一只飛蛾,這顯然是由于飛蛾受光和熱的吸引,飛到了觸點(diǎn)上,然后被高電壓擊死。與Bug相對(duì)應(yīng),人們將發(fā)現(xiàn)Bug并加以糾正的過(guò)程叫做“Debug”(中文稱作“調(diào)試”),意即“捉蟲(chóng)子”或“殺蟲(chóng)子”。
調(diào)試其實(shí)就是找出bug,計(jì)算機(jī)有bug一定是你程序的問(wèn)題。所有發(fā)生的程序的問(wèn)題都是有跡可循的,我們只需要順藤摸瓜最后一步步解決。
一名優(yōu)秀的程序員,必然是一名優(yōu)秀的偵探。每一次的調(diào)試其實(shí)就是破案的過(guò)程。
調(diào)試:英文DeBug,又稱作是除錯(cuò),是發(fā)現(xiàn)和減少計(jì)算機(jī)程序設(shè)備中和電子儀器錯(cuò)誤的過(guò)程。
代價(jià)最小的是程序員,代價(jià)最大的是用戶。
通常為調(diào)試版本,它包含的調(diào)試信息,并且不會(huì)做進(jìn)行任何的優(yōu)化,便于程序員的調(diào)試信息。
概念:
1937年,美國(guó)青年霍華德·艾肯找到IBM公司為其投資200萬(wàn)美元研制計(jì)算機(jī),第一臺(tái)成品艾肯把它取名為:馬克1號(hào)(mark1),又叫“自動(dòng)序列受控計(jì)算機(jī)”,從這時(shí)起IBM公司由生產(chǎn)制表機(jī),肉鋪磅秤,咖啡研磨機(jī)等亂七八糟玩意兒行業(yè),正式跨進(jìn)“計(jì)算機(jī)”領(lǐng)地。為馬克1號(hào)編制程序的是哈佛的一位女?dāng)?shù)學(xué)家格蕾絲·霍珀,有一天,她在調(diào)試程序時(shí)出現(xiàn)故障,拆開(kāi)繼電器后,發(fā)現(xiàn)有只飛蛾被夾扁在觸點(diǎn)中間,從而“卡”住了機(jī)器的運(yùn)行。于是,霍珀詼諧的把程序故障統(tǒng)稱為“臭蟲(chóng).............(BUG)”,把排除程序故障叫DEBUG,而這奇怪的“稱呼”,后來(lái)成為計(jì)算機(jī)領(lǐng)域的專業(yè)行話。從而debug意為排除程序故障的意思。
稱之為發(fā)布版本,它往往是根據(jù)各種進(jìn)行了優(yōu)化,使得程序的代碼都是最佳優(yōu)的,以便讓用戶更好的去使用。
Debug和Release編譯方式的本質(zhì)區(qū)別
Debug 通常稱為調(diào)試版本,它包含調(diào)試信息,并且不作任何優(yōu)化,便于程序員調(diào)試程序。
Release 稱為發(fā)布版本,它往往是進(jìn)行了各種優(yōu)化,使得程序在代碼大小和運(yùn)行速度上都是最優(yōu)的,以便用戶很好地使用。還有大小的區(qū)別,因?yàn)镈ebug的版本是可以進(jìn)行調(diào)試的(包含了相應(yīng)的調(diào)試信息),而Release版本是不能進(jìn)行調(diào)試的。
Debug 和 Release 的真正秘密,在于一組編譯選項(xiàng)。
下面列出了分別針對(duì)二者的選項(xiàng)
(當(dāng)然除此之外還有其他一些,如/Fd /Fo,但區(qū)別并不重要,通常他們也不會(huì)引起 Release 版錯(cuò)誤,在此不討論)
/MDd /MLd 或 /MTd 使用 Debug runtime library(調(diào)試版本的運(yùn)行時(shí)刻函數(shù)庫(kù))
/Od 關(guān)閉優(yōu)化開(kāi)關(guān)
/D "_DEBUG " 相當(dāng)于 #define _DEBUG,打開(kāi)編譯調(diào)試代碼開(kāi)關(guān)(主要針對(duì) assert函數(shù))
/ZI 創(chuàng)建 Edit and continue(編輯繼續(xù))數(shù)據(jù)庫(kù),這樣在調(diào)試過(guò) 程中如果修改了源代碼不需重新編譯 /GZ 可以幫助捕獲內(nèi)存錯(cuò)誤
/Gm 打開(kāi)最小化重鏈接開(kāi)關(guān),減少鏈接時(shí)間
/MD /ML 或 /MT 使用發(fā)布版本的運(yùn)行時(shí)刻函數(shù)庫(kù)
/O1 或 /O2 優(yōu)化開(kāi)關(guān),使程序最小或最快
/D "NDEBUG " 關(guān)閉條件編譯調(diào)試代碼開(kāi)關(guān)(即不編譯assert函數(shù))
/GF 合并重復(fù)的字符串,并將字符串常量放到只讀內(nèi)存,防止 被修改
實(shí)際上,Debug 和 Release 并沒(méi)有本質(zhì)的界限,他們只是一組編譯選項(xiàng)的集合,編譯器只是按照預(yù)定的選項(xiàng)行動(dòng)。事實(shí)上,我們甚至可以修改這些選項(xiàng),從而得到優(yōu)化過(guò)的調(diào)試版本或是帶跟蹤語(yǔ)句的發(fā)布版本。
- 采用Debug的話,如果用Debug代碼來(lái)編譯可執(zhí)行程序的話,我們也會(huì)產(chǎn)生一個(gè)Debug的版本的一個(gè)可執(zhí)行程序
- 采用Release的話,就是發(fā)布版本,可執(zhí)行的程序。——(簡(jiǎn)化)
#include#includeint main(void){ int i = 0; int arr[10] = {1,2,3,4,5,6,7,8,9,10}; for(i=0;i<=12;i++) { printf("hello C/n"); arr[i] = 0; } system("pause");}
大家可以分別試一下就會(huì)發(fā)現(xiàn)不同之處了,分別用Debug和Release運(yùn)行以下程序。這里是當(dāng)你for循環(huán)的結(jié)果為假的時(shí)候,它的i又會(huì)重置為0,然后一直這個(gè)樣子重復(fù)循環(huán)打印for語(yǔ)句的循環(huán)內(nèi)容。因?yàn)閍rr這里跟i它們兩個(gè)人是同一塊空間,那么當(dāng)你改變arr[i]的時(shí)候int i也會(huì)改變。因?yàn)樗鼈兊牡刂肥且粯拥模圆艜?huì)改變。
由于這個(gè)程序涉及范圍到棧區(qū)一些相關(guān)的知識(shí)點(diǎn)的內(nèi)容,在這里我跟大家簡(jiǎn)單的說(shuō)下。
棧區(qū):棧區(qū)的默認(rèn)使用是先使用高地址處的空間,然后在使用低地址處的空間。數(shù)組的下標(biāo)隨著增長(zhǎng),地址是由低到高變化的。當(dāng)然如果你在不同的編譯器上運(yùn)行它的死循環(huán)的位置可能不同。你們也可以在不同的編譯器上運(yùn)行一下對(duì)比一下
運(yùn)行:Ctrl + F11
使用快捷鍵Ctrl + F11可以快速運(yùn)行當(dāng)前選中的資源文件。
調(diào)試:F11:是逐步 它是會(huì)進(jìn)入函數(shù)的 把程序細(xì)化到步
shift + F11,跳出函數(shù)
F10 是逐行 在某條語(yǔ)句調(diào)用一個(gè)函數(shù)的時(shí)候 它不會(huì)進(jìn)入(除非那里設(shè)有斷點(diǎn))
F9:切換斷點(diǎn)
使用快捷鍵F11可以快速調(diào)試當(dāng)前選中的資源文件。
斷點(diǎn)調(diào)試操作:F5、F6、F7、F8
F5和F9的快捷鍵可以進(jìn)行配合使用。
在斷點(diǎn)調(diào)試時(shí),快捷鍵F6是執(zhí)行下一步(單步跳過(guò));F5是執(zhí)行當(dāng)前調(diào)用內(nèi)部細(xì)節(jié)步驟的下一步(單步跳入);F7是跳過(guò)方法內(nèi)部的執(zhí)行步驟,直接返回到方法外的下一步(單步返回);F8是跳出斷點(diǎn)調(diào)試(跳過(guò)調(diào)試,繼續(xù)執(zhí)行代碼,在下一個(gè)斷點(diǎn)處暫停再次進(jìn)入斷點(diǎn)調(diào)試)。
ctrl + F5:開(kāi)始執(zhí)行不調(diào)試,如果你想讓程序而不調(diào)試就可以進(jìn)行使用。
自動(dòng)窗口:當(dāng)我們程序在執(zhí)行中的時(shí)候,打開(kāi)自動(dòng)窗口,自動(dòng)的把某些程序的上下文變量自動(dòng)給你觀察,這就是自動(dòng)窗口的功能。
局部變量:和自動(dòng)窗口差不多其實(shí),但是它有一個(gè)缺點(diǎn)是它不能想監(jiān)視誰(shuí)就監(jiān)視誰(shuí)。
監(jiān)視:監(jiān)視這個(gè)作用就比較好了,當(dāng)你想監(jiān)視的話就輸入那個(gè)變量的值,它就會(huì)呈現(xiàn)在你的監(jiān)視當(dāng)中,這樣你就可以隨時(shí)隨地的去進(jìn)行觀察那個(gè)變量了。(監(jiān)視窗口可以說(shuō)是博主用的最多的了)
內(nèi)存:如果我們想進(jìn)行觀察當(dāng)前程序執(zhí)行的內(nèi)存的話,這個(gè)時(shí)候就是你輸入觀察的內(nèi)存信息了。
(內(nèi)存窗口也是用的可以說(shuō)是非常多的了)
調(diào)用堆棧:在這里簡(jiǎn)單的和各位小伙伴們說(shuō)下,像棧一樣的邏輯給大家給展示出來(lái)它的一個(gè)邏輯,頂上往前放數(shù)據(jù)再往頂上出數(shù)據(jù),可以很好反饋程序當(dāng)中的代碼的調(diào)棧的調(diào)用邏輯。
初學(xué)者掌握調(diào)試的內(nèi)容可以達(dá)到事半功倍的效果,多多使用調(diào)試可以提高程序執(zhí)行代碼的效率。
- 代碼整潔且規(guī)范
- 注釋清晰,且通俗易懂(代指寫(xiě)代碼的人)
- 可讀性,有效性,可維護(hù)性
- bug盡量能夠達(dá)到自己能夠預(yù)期的范圍之內(nèi),就是bug少,或者幾乎沒(méi)有bug
- 文檔齊全,不亂去堆放?
- 養(yǎng)成良好的編碼風(fēng)格
- 注釋必要的還是要去添加,提高代碼的可讀性
- 避免編碼的陷阱
- 盡量使用const
- 使用assert,頭文件#include
,在assert();里面的表達(dá)式如果為真的話,assert表達(dá)式為真就什么都不會(huì)發(fā)生,如果assert的表達(dá)式為假,那么就會(huì)報(bào)錯(cuò)。
在這里簡(jiǎn)單的跟大家介紹一下const的關(guān)鍵字:const修飾的數(shù)據(jù)是常類(lèi)型,常類(lèi)型的變量或者對(duì)象的值是不可以被該變的,也就是被它修飾過(guò)的是常量,相比之下const常量和#define是有點(diǎn)類(lèi)似的,但是在我們用數(shù)組的時(shí)候還是要區(qū)分一下,因?yàn)閿?shù)組里面 [常量表達(dá)式],此時(shí)我如果 const int n = 10 假設(shè)賦值給arr數(shù)組,int arr[n] = {0};結(jié)果是不行的,雖然加了const關(guān)鍵字,但實(shí)際上也只是變量只不過(guò)是不能被修改的變量。那么如果我們這里用的是#define—定義符號(hào)常量就可以了。??
#include#includeint My_strlen(const char* pb){ int Count = 0;//計(jì)數(shù) assert(*pb != NULL);//保證指針的有效性 NULL —— 空指針 while (*pb != "/0") { Count++; *pb++; } return Count;}int main(void){ char arr[20] = "nihao C"; int ret = My_strlen(arr); printf("arr(strlen) = %d/n", ret); return 0;}
最后,我想跟大家說(shuō)程序遇到bug不要害怕,勇敢的去面對(duì)它吧,加油奧里給!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/121140.html
摘要:調(diào)試的基本步驟發(fā)現(xiàn)程序錯(cuò)誤的存在以隔離消除等方式對(duì)錯(cuò)誤進(jìn)行定位確定錯(cuò)誤產(chǎn)生的原因提出糾正錯(cuò)誤的解決辦法對(duì)程序錯(cuò)誤予以改正重新測(cè)試和版本的介紹通常稱為調(diào)試版本,它包含調(diào)試信息,并且不做任何優(yōu)化,以便于程序員調(diào)試。 ...
摘要:而就是告訴程序在那里停下來(lái)進(jìn)行單步調(diào)試,俗稱斷點(diǎn)。面向,專為異步而生的斷點(diǎn)調(diào)試功能。中的調(diào)試技巧元素的控制臺(tái)書(shū)簽開(kāi)發(fā)者工具和都提供了書(shū)簽功能,用于顯示你在元素標(biāo)簽頁(yè)或標(biāo)簽頁(yè)中最后點(diǎn)擊的元素。 寫(xiě)在前面本文包括瀏覽器調(diào)試,不包括web移動(dòng)端調(diào)試。本文調(diào)試均在chrome瀏覽器進(jìn)行 alert 這個(gè)不用多說(shuō)了,不言自明 console 基本輸出 想必大家都在用console.log在控制...
摘要:而就是告訴程序在那里停下來(lái)進(jìn)行單步調(diào)試,俗稱斷點(diǎn)。面向,專為異步而生的斷點(diǎn)調(diào)試功能。中的調(diào)試技巧元素的控制臺(tái)書(shū)簽開(kāi)發(fā)者工具和都提供了書(shū)簽功能,用于顯示你在元素標(biāo)簽頁(yè)或標(biāo)簽頁(yè)中最后點(diǎn)擊的元素。 寫(xiě)在前面本文包括瀏覽器調(diào)試,不包括web移動(dòng)端調(diào)試。本文調(diào)試均在chrome瀏覽器進(jìn)行 alert 這個(gè)不用多說(shuō)了,不言自明 console 基本輸出 想必大家都在用console.log在控制...
摘要:而就是告訴程序在那里停下來(lái)進(jìn)行單步調(diào)試,俗稱斷點(diǎn)。面向,專為異步而生的斷點(diǎn)調(diào)試功能。中的調(diào)試技巧元素的控制臺(tái)書(shū)簽開(kāi)發(fā)者工具和都提供了書(shū)簽功能,用于顯示你在元素標(biāo)簽頁(yè)或標(biāo)簽頁(yè)中最后點(diǎn)擊的元素。 寫(xiě)在前面本文包括瀏覽器調(diào)試,不包括web移動(dòng)端調(diào)試。本文調(diào)試均在chrome瀏覽器進(jìn)行 alert 這個(gè)不用多說(shuō)了,不言自明 console 基本輸出 想必大家都在用console.log在控制...
閱讀 2984·2021-11-23 09:51
閱讀 1011·2021-09-26 09:55
閱讀 3958·2021-09-22 14:58
閱讀 1484·2021-09-08 09:35
閱讀 1082·2021-08-26 14:16
閱讀 886·2019-08-23 18:17
閱讀 2067·2019-08-23 16:45
閱讀 704·2019-08-23 15:55