Ⅰ 單片機軟體調試方法,請問單片機程序調試都有什麼方法
用keil調試,主要是設置斷點,單步執行,運行到游標處,查看運行時間,監視變數和表達式的值,這些都是常用的手段,你仔細看看工具欄就知道了
Ⅱ 程序調試的方法
一,簡單調試方法:步驟
1,在程序中插入列印語句、優點是能夠顯示程序的動態過程,比較容易檢查源程序的有關信息。缺點是效率低,可能輸入大量無關的數據,發現錯誤帶有偶然性。
2,運行部分程序。有時為了測試某些被懷疑有錯的程序段,卻將整個程序反復執行許多次,在這種情況下,應設法使被測程序只執行需要檢查的程序段,以提高效率。
3,藉助調試工具。目前大多數程序設計語言都有專門的調試工具,可以用這些工具來分析程序的動態行為。
二,回溯法排錯。確定最先發現錯誤症狀的地方,人工沿程序的控制流往回追蹤源程序代碼,直到找到錯誤或范圍。
三,歸納法排錯。是一種系統化的思考方法,是從個別推斷全體的方法,這種方法從線索(錯誤徵兆出發),通過分析這些線索之間的關系找出故障。主要有4步:
(1)收集有關數據。收集測試用例,弄清測試用例觀察到哪些錯誤徵兆,以及在什麼情況下出現錯誤等信息。
(2)組織數據。整理分析數據,以便發現規律,即什麼條件下出現錯誤,什麼條件下不出現錯誤。
(3)導出假設。分析研究線索之間的關系,力求找出它們的規律,從而提出關於錯誤的一個或多個假設,如果無法做出假設,則應設計並執行更多的測試用例,以便獲得更多的數據。
(4)證明假設。假設不等於事實,證明假設的合理性是極其重要的,不經證明就根據假設排除錯誤,往往只能消除錯誤的徵兆或只能改正部分錯誤。證明假設的方法是用它解釋所有原始的測試結果,如果能圓滿地解釋一切現象,則假設得到證明,否則要麼是假設不成立或不完備,要麼是有多個錯誤同時存在。
四,演繹法排錯 。設想可能的原因,用已有的數據排除不正確的假設,精化並證明餘下的假設。
五、對分查找法。如果知道每個變數子啊程序內若干個關鍵點上的正確值,則可用賦值語句或輸入語句在程序中的關鍵點附近「注入」這些變數的正確值,然後檢查程序的輸出。如果輸出結果是正確的,則表示錯誤發生在前半部分,否則,不妨認為錯誤在後半部分。這樣反復進行多次,逐漸逼近錯誤位置。
Ⅲ java程序調試的5種方法
1.debug。斷點調試。
2.輸出消息。system.out.println();來調試。
3.動態代理(Dynamic Proxy)。動態代理是一個特定的Java特性,它允許開發者引入proxy類,加進某一給定類之前,並通過某一給定介面截獲所有調用。你可以在很短時間內用一個普通代理設置一個虛擬事件處理器,來查看事件發生順序。當需要理解事件處理器時這是最簡單和快捷的方法。
4.運行時剖析器(Run-time Profiler)。剖析器是通過特定的JVM hooks在系統中跟蹤所有調用的強大工具。但是用它來跟蹤執行過程是大才小用。
5.Aspects。面向方面編程。它是截獲你的代碼執行既快速又容易的方法。你可以圍繞方法、構造器、屬性訪問等等有選擇地設置hook,而不需要修改原始代碼。在這些hook中,你可以列印調試消息。
1.2常用的。3.4.5網上找的。
Ⅳ 程序調試主要對程序進行何種調試常用的測試數據有哪幾種
需求獲取的常用方法有哪些 1)用戶訪談 用戶訪談是一種最基本的需求獲取手段,它是指分析人員以個別訪談或小組合議的形式與用戶進行初步的溝通。用戶訪談的形式包括結構化和非結構化兩種,結構化是指分析人員按照——定準則事先准備好一系列問題,通過用戶對問題的回答來獲取有關目標軟體方面的內容;非結構化則是只列以一個粗糙的想法,根據訪談的民體情況來進行發揮。 2)用戶調查 在進行用戶防談時,由於很多關鍵人員的時間有限,不易安排過多的時間或者項日涉及的客戶面較廣。不可能——一訪談。因此,就需要藉助用戶調杏的方法,通過精心設計要問的問題,然後下發到相關的人員手中,讓他們填寫,再從所填寫的內容中獲取系統的需求倍息,這樣就可以克服上述的問題。 用戶調查最大的不足就是缺乏靈活性,而且可能存在受調查人員不能很好表述自己想法的限制。 3)現場觀摩 俗話說,百聞石如一見,對於許多較為復雜的流程和系統而言,是很難用自然語言表達清楚的。因此,為了能夠對系統的需求獲得全面的了解,實際觀察用戶的操作過程就是一種行之合效的方法。現場觀摩就是走到客戶的工作場所,一邊觀察,一邊聽客戶講解,甚至可以安排人員跟隨用戶一起工作一段時間。這樣就可以使得分析人員對客戶的需求有更加直觀的理解。但是,在現場觀摩過程中必須切記;建造軟體系統不僅僅只是為了模擬客戶的手下操作過程,還必須將最好的經濟效益、最快的處理速度、最合理的操作流程和最友好的用戶界而等作為軟體設計的目標。 4)文檔考古 文檔考古是指對歷史存在的—些文檔進行研究,從帶有數據的文件、表單、報表等文檔中獲取所需信息的過程。對於一些數據流程比較復雜的、工作表單較多的項目來說,就可以應用這種方法。 5)建立聯合分析小組 在系統開發時,系統分析員和用戶之間由於知識結構的差異,難免存在難逾越的交流鴻溝。 用廣提供的需求信息,在系統分析員看來可能是零散和片面甚至無法理解的。因此,為了能夠減少交流上的問題,就需要一個領域專家來幫助進行溝通,即可以建立一個由用戶、系統分析員和領域專家參加的聯合分析小組來共同完成需求的獲地。 6)原型法 原型是在軟體開發中被廣泛使用的一種工具,在軟體系統的很多開發階段都起著非常重要的作用。原型法就是盡可能快地建造一個祖糙的系統,這系統實現了目標系統的某些或全部功能,但是這個系統可能在可靠性、界面的友好性或其他方向上存在缺陷。建造這樣一個系統的目的是為了看,考察某一方面的可行性。如演算法的可行性,技術的可行性,或考察是否滿足用戶的需求等。原型是在最終系統產生之前的一個局部真實表現,可以讓人們能夠對一些具體問題進行基於文物的有效溝通,從而幫助人們盡早解決軟體開發個存在的各種不確定性。 7)模型驅動 前面的面談、原型、觀察以及文檔審查等方法可以通過執行一些具體的獲取行為來對系統需求進行認知和理解。但是大多數軟體系統,尤其是對於復雜的系統而言,它們的需求獲取任務絕不是可以通道一兩次這樣簡單的獲取行為就能夠完成的。為了能夠使得獲取行為相互配合、減少不必要的精力耗費和防止出現獲取信息的遺漏,可以採用模型驅動的方法。 8)基於上下文的方法 軟體系統是作為一個整體存在的,它通過和環境的交互來解決用戶的問題,滿足用戶的需求。軟體系統中的每項功能都是依存於一定的背景和上下文環境,因此,要正確地理解系統的功能就必須要正確地理解它的背景和上下文知識。基於上下文的方法就是注重於系統的環境、開發組織的業務背景、涉眾的特徵以及目標等。與前面的方法相比,它更加註重用戶在—定環境下表現出來的行為,通過分析用戶的行為得到信息。 說明軟體測試和調試的目的有何區別 1、目的不同 軟體測試的目的是發現錯誤,至於找出錯誤的原因和錯誤發生的地方不是軟體測試的任務,而是調試的任務.調試的目的是為了證明程序的正確,因此它必須不斷地排除錯誤.它們的出發點不一樣。前者是挑錯,是一種挑剔過程,屬於質盤保證活動。後者是排錯,是一種排除過程,是編碼活動的一部分. 2、任務不同 既然軟體測試屬於質量保證活動,因此它貫穿於整個開發過程.從需求分析開始,就要制訂軟體測試計劃,軟體設計時要設計系統軟體測試、集成側試用例,編碼階段要設計單元軟體測試用例並進行單元軟體測試,軟體測試階段要進行集成軟體測試、系統軟體測試等,直到產品交付。只要有修改就有軟體測試,產品交付後同樣。它是比較有規律的活動,有系統的方法、原則作指導。 而調試是編碼活動的一部分,因此有編碼就有調試.它的任務主要就是排錯。調試的方法經常與使用的開發工具有關,例如:解釋型的開發工具可以互動式調試,編譯型開發工具就很難較好地查錯。當然它有一些啟發式的方法,它是一種比較依賴開發人員經驗的活動。 3、指導原則和方法不同 軟體側試是一種有規律的活動,有一系列軟體軟體測試的原則.其中主要是制訂側試計劃,然後嚴格執行.其次是一種挑剔性行為,因此它不但要側試軟體應該做的,還需要側試軟體不應該做的事情。調試所遵循的規律主要是一些啟發式規則,是一個推理過程。例如使用歸納法、演繹法、回溯法等。 軟體測試的輸出是預知的,其軟體測試用例必須包括預期的結果,而調試的輸出大多是不可預見的,需要調試者去解釋、去發現產生的原因。 4、操作者 因為心理狀態是軟體測試程序的障礙,所以執行軟體測試的人一般不是開發人員,以使軟體測試更客觀、更有效,而調試人員一般都是開發人員.
Ⅳ 哪位大師講講代碼調試都有哪些手段
調試程序bug的方法很多,比如最基礎的加斷點,單步執行等,另外還可以藉助一些其他功能,比如調用堆棧,可以看到出錯時調用的那個函數,內存窗口,查看內存,監視窗口可以方便的查看各個變數的值等。
Ⅵ C語言程序設計中軟體調試方法有哪三種
軟體調試主要採用以下三種方法:
強行排錯法:作為傳統的調試方法,其過程可概括為設置斷點、程序暫停、觀察程序狀態、繼續運行程序。
回溯法:該方法適合於小規模程序的排錯、即一旦發現了錯誤,先分析錯誤徵兆,確定最先發現「症狀」的位置。
原因排除法:原因排除法是通過演繹和歸納,以及二分法來實現。
Ⅶ 在嵌入式系統開發中,常用的程序調試手段有哪些
不同系統下有不同的軟體支持,,,
wince
vxworks
linux
這是系統,
好多都是交叉編譯,
windows下也有好多工具,如:ADS
,SDT2.51
linux下也有好多,和gcc相關的工具,
不知道常用的調試手段有什麼
不過有模擬的工具吧。應該能調試吧。
手動,讓程序自己輸出一些信息,還有設置一些中斷也行吧。。。
Ⅷ 求安卓程序開發中常用的調試方法
可以在需要查看信息的地方log.i(),括弧里填你需要的字元串或者表達式(字元串形式)。然後在logcat里就能看到這句是否執行,或是獲得的信息是不是你想要的信息
Ⅸ 調試程序方法
1,在程序中插入列印語句、優點是能夠顯示程序的動態過程,比較容易檢查源程序的有關信息。確定是效率低,可能輸入大量無關的數據,發現錯誤帶有偶然性。
2,運行部分程序。有時為了測試某些被懷疑有錯的程序段,卻將整個程序反復執行許多次,在這種情況下,應設法使被測程序只執行需要檢查的程序段,以提高效率。
3,藉助調試工具。目前大多數程序設計語言都有專門的調試工具,可以用這些工具來分析程序的動態行為。
Ⅹ 對C語言進行調試的最好方法是什麼
要了解調試程序的最好方法,首先要分析一下調試過程的三個要素:
應該用什麼工具調試一個程序?
用什麼辦法才能找出程序中的錯誤?
怎樣才能從一開始就避免錯誤?
應該用什麼工具調試一個程序?
有經驗的程序員會使用許多工具來幫助調試程序,包括一組調試程序和一些"lint」程序,當然,編譯程序本身也是一種調試工具。
在檢查程序中的邏輯錯誤時,調試程序是特別有用的,因此許多程序員都把調試程序作為基本的調試工具。一般來說,調試程序能幫助程序員完成以下工作:
(1)觀察程序的運行情況
僅這項功能就使一個典型的調試程序具備了不可估量的價值。即使你花了幾個月的時間精心編寫了一個程序,你也不一定完全清楚這個程序每一步的運行情況。如果程序員忘記了某些if語句、函數調用或分支程序,可能會導致某些程序段被跳過或執行,而這種結果並不是程序員所期望的。不管怎樣,在程序的執行過程中,尤其是當程序有異常表現時,如果程序員能隨時查看當前被執行的是那幾行代碼,那麼他就能很好地了解程序正在做什麼以及錯誤發生在什麼地方。
(2)設置斷點
通過設置斷點可以使程序在執行到某一點時暫時停住。當你知道錯誤發生在程序的哪一部分時,這種方法是特別有用的。你可以把斷點設置在有問題的程序段的前面、中間或後面。當程序執行到斷點時,就會暫時停住,此時你可以檢查所有局部變數、參數和全局變數的值。如果一切正常,可以繼續執行程序,直到遇到另一個斷點,或者直到引起問題的原因暴露出來。
(3)設置監視
程序員可以通過調試程序監視一個變數,即連續地監視一個變數的值或內容。如果你清楚一個變數的取值范圍或有效內容,那麼通過這種方法就能很快地找出錯誤的原因。此外,你可以讓調試程序替你監視變數,並且在某個變數超出預先定義的取值范圍或某個條件滿足時使程序暫停執行。如果你知道變數的所有行為,那麼這么做是很方便的。
好的調試程序通常還提供一些其它功能來簡化調試工作。然而,調試程序並不是唯一的調試工具,lint程序和編譯程序本身也能提供很有價值的手段來分析程序的運行情況。
注意:lint程序能分辨數百種常見的編程錯誤,並且能報告這些錯誤發生在程序的哪一部分。盡管其中有一些並不是真正的錯誤,但大部分還是有價值的。
lint程序和編譯程序所提供的一種典型功能是編譯時檢查(compile—time checks),這種功能是調試程序所不具備的。當用這些工具編譯你的程序時,它們會找出程序中有問題的程序段,可能產生意想不到的效果的程序段,以及常見的錯誤。下面將分析幾個這種檢查方式的應用例子,相信對你會有所幫助。
等於運算符的誤用
編譯時檢查有助於發現等於運算符的誤用。請看下述程序段:
void foo(int a,int b)
{
if ( a = b )
{
/ * some code here * /
}
}
這種類型的錯誤一般很難發現!程序並沒有比較兩個變數,而是把b的值賦給了a,並且在b不為零的條件下執行if體。一般來說,這並不是程序員所希望的(盡管有可能)。這樣一來,不僅有關的程序段將被執行錯誤的次數,並且在以後用到變數a時其值也是錯誤的。
未初始化的變數
編譯時檢查有助於發現未初始化的變數。請看下面的函數:
void average ( float ar[], int size )
{
float total;
int a;
for( a = 0;a<size; ++a)
{
total+=ar[a];
}
printf(" %f\n", total / (float) size );
}
這里的問題是變數total沒有被初始化,因此它很可能是一個隨機的無用的數。數組所有元素的值的和將與這個隨機數的值相加(這部分程序是正確的),然後輸出包括這個隨機數在內的一組數的平均值。
變數的隱式類型轉換
在有些情況下,C語言會自動將一種類型的變數轉換為另一種類型。這可能是一件好事(程序員不用再做這項工作),但是也可能會產生意想不到的效果。把指針類型隱式轉換成整型恐怕是最糟糕的隱式類型轉換。
void sort( int ar[],int size )
{
/* code to sort goes here * /
}
int main()
{
int arrgy[10];
sort( 10, array );
}
上述程序顯然不是程序員所期望的,雖然它的實際運行結果難以預測,但無疑是災難性的。
用什麼辦法才能找出程序中的錯誤?
在調試程序的過程中,程序員應該記住以下幾種技巧:
先調試程序中較小的組成部分,然後調試較大的組成部分
如果你的程序編寫得很好,那麼它將包含一些較小的組成部分,最好先證實程序的這些部分是正確的。盡管程序中的錯誤並不一定發生在這些部分中,但是先調試它們有助於你理解程序的總體結構,並且證實程序的哪些部分不存在錯誤。進一步地,當你調試程序中較大的組成部分時,你就可以確信那些較小的組成部分是正常工作的。
徹底調試好程序的一個組成部分後,再調試下一個組成部分
這一點非常重要。如果證實了程序的一個組成部分是正確的,不僅能縮小可能存在錯誤的范圍,而且程序的其它組成部分就能安全地使用這部分程序了。這里應用了一種很好的經驗性原則,簡單地說就是調試一段代碼的難度與這段代碼長度的平方成正比,因此,調試一段20行的代碼比調試一段10行的代碼要難4倍。因此,在調試過程中每次只把精力集中在一小段代碼上是很有幫助的。當然,這僅僅是一個總的原則,具體使用時還要視具體情況而定。
連續地觀察程序流(flow)和數據的變化
這一點也很重要!如果你小心仔細地設計和編寫程序,那麼通過監視程序的輸出你就能准確地知道正在執行的是哪部分代碼以及各個變數的內容都是什麼。當然,如果程序表現不正常,你就無法做到這一點。為了做到這一點,通常只能藉助於調試程序或者在程序中加入大量的print語句來觀察控制流和重要變數的內容。
始終打開編譯程序警告選項 並試圖消除所有警告
在開發程序的過程中,你自始至終都要做到這一點,否則,你就會面臨一項十分繁重的工作。盡管許多程序員認為消除編譯程序警告是一項繁瑣的工作,但它是很有價值的。編譯程序給出警告的大部分代碼至少都是有問題的,因此用一些時間把它們變成正確的代碼是值得的;而且,通過消除這些警告,你往往會找到程序中真正發生錯誤的地方。
准確地縮小存在錯誤的范圍
如果你能一下子確定存在錯誤的那部分程序並在其中找到錯誤,那就會節省許多調試時間,並且你能成為一個收入相當高的專業調試員。但事實上,我們並不能總是一下子就命中要害,因此,通常的做法是逐步縮小可能存在錯誤的程序范圍,並通過這種過程找出真正存在錯誤的那部分程序。不管錯誤是多麼難於發現,這種做法總是有效的。當你找到這部分程序後,就可以把所有的調試工作集中到這部分程序上了。不言而喻,准確地縮小范圍是很重要的,否則,最終集中精力調試的那部分程序很可能是完全正確的。
如何從一開始就避免錯誤?
有這樣一句諺語——「防患於未然」,它的意思是避免問題的出現比出現問題後再想辦法彌補要好得多。這在計算機編程中也是千真萬確的!在編寫程序時,一個經驗豐富的程序員所花的時間和精力要比一個缺乏經驗的程序員多得,但正是這種耐心和嚴謹的編程風格使經驗豐富的程序員往往只需花很少的時間來調試程序,而且,如果此後程序要解決某個問題或做某種改動,他便能很快地修正錯誤並加入相應的代碼。相反,對於一個粗製濫造的程序,即使它總的來說還算正確,那麼改動它或者修正其中一個很快就暴露出來的錯誤,都會是一場惡夢。
一般來說,按結構化程序設計原則編寫的程序是易於調試和修改的,下面將介紹其中的一些原則。
程序中應有足夠的注釋
有些程序員認為注釋程序是一項繁瑣的工作,但即使你從來沒想過讓別人來讀你的程序,你也應該在程序中加入足夠的注釋,因為即使你現在認為清楚明了的語句,在幾個月以後往往也會變得晦澀難懂。這並不是說注釋越多越好,過多的注釋有時反而會混淆代碼的原意。但是,在每個函數中以及在執行重要功能或並非一目瞭然的代碼前加上幾行注釋是必要的。下面就是一段注釋得較好的代碼:
/*
* Compute an integer factorial value using recursion.
* Input an integer number.
* Output : another integer
* Side effects : may blow up stack if input value is * Huge *
*/
int factorial ( int number)
{
if ( number < = 1)
return 1; /* The factorial of one is one; QED * /
else
return n * factorial( n - 1 );
/ * The magic! This is possible because the factorial of a
number is the number itself times the factorial of the
number minus one. Neat! * /
}
函數應當簡潔
按照前文中曾提到的這樣一條原則——調試一段代碼的難度和這段代碼長度的平方成正比——函數編寫得簡潔無疑是有益的。但是,需要補充的是,如果一個函數很簡潔,你就應該多花一點時間去仔細地分析和檢查它,以確保它准確無誤。此後你可以繼續編寫程序的其餘部分,並且可以對剛才編寫的函數的正確性充滿信心,你再也不需要檢查它了。對於一段又長又復雜的常式,你往往是不會有這樣的信心的。
編寫短小簡潔的函數的另一個好處是,在編寫了一個短小的函數之後,在程序的其它部分就可以使用這個函數了。例如,如果你在編寫一個財務處理程序,那麼你在程序的不同部分可能都需要按季、按月、按周或者按一月中的某一天等方式來計算利息。如果按非結構化原則編寫程序,那麼在計算利息的每一處都需要一段獨立的代碼,這些重復的代碼將使程序變得冗長而難讀。然而,你可以把這些任務的實現簡化為下面這樣的一個函數:
/*
* ComDllte what the "real" rate of interest would be
* for a given flat interest rate, divided into N segments
*/
double Compute Interest( double Rate, int Segments )
{
int a;
double Result = 1.0;
Rate /= (double) Segments;
for( a = 0; a< Segments ; ++a )
Result * =Rate;
return Result;
}
在編寫了上述函數之後,你就可以在計算利息的每一處調用這個函數了。這樣一來,你不僅能有效地消除每一段復制的代碼中的錯誤,而且大大縮短了程序的長度,簡化了程序的結構。這種技術往往還會使程序中的其它錯誤更容易被發現。
當你習慣了用這種方法把程序分解為可控制的模塊後,你就會發現它還有更多的妙用。
程序流應該清晰,避免使用goto語句和其它跳轉語句
這條原則在計算機技術領域內已被廣泛接受,但在某些圈子中對此還很有爭議。然而,人們也一致認為那些通過少數語句使程序流無條件地跳過部分代碼的程序調試起來要容易得多,因為這樣的程序通常更加清晰易懂。許多程序員不知道如何用結構化的程序結構來代替那些「非結構化的跳轉」,下面的一些例子說明了應該如何完成這項工作:
for( a = 0; a<100s ++a)
{
Func1( a );
if (a = = 2 ) continue;
Func2( a );
}
當a等於2時,這段程序就通過continue語句跳過循環中的某余部分。它可以被改寫成如下的形式:
for( a = 0; a<100; ++a)
{
Func1 (a);
if (a !=2 )
Func2(a) ;
}
這段程序更易於調試,因為花括弧內的代碼清楚地顯示了應該執行和不應該執行什麼。那麼,它是怎樣使你的代碼更易於修改和調試的呢?假設現在要加入一些在每次循環的最後都要被執行的代碼,在第一個例子中,如果你注意到了continue語句,你就不得不對這段程序做復雜的修改(不妨試一下,因為這並非是顯而易見的!);如果你沒有注意到continue語句,那麼你恐怕就要犯一個難以發現的錯誤了。在第二個例子中,要做的修改很簡單,你只需把新的代碼加到循環體的末尾。
當你使用break語句時,可能會發生另外一種錯誤。假設你編寫了下面這樣一段程序:
for (a =0) a<100; ++a)
{
if (Func1 (a) ==2 )
break;
Func2 (a) ;
}
假設函數Funcl()的返回值永遠不會等於2,上述循環就會從1進行到100;反之,循環在到達100以前就會結束。如果你要在循環體中加入代碼,看到這樣的循環體,你很可能就會認為它確實能從0循環到99,而這種假設很可能會使你犯一個危險的錯誤。另一種危險可能來自對a值的使用,因為當循環結束後,a的值並不一定就是100。
c語言能幫助你解決這樣的問題,你可以按如下形式編寫這個for循環:
for(a=O;a<100&&Func1(a)!=2;++a)
上述循環清楚地告訴程序員:「從0循環到99,但一旦Func1()等於2就停止循環」。因為整個退出條件非常清楚,所以程序員此後就很難犯前面提到的那些錯誤了。
函數名和變數名應具有描述性
使用具有描述性的函數和變數名能更清楚地表達代碼的意思——並且在某種程度上這本身就是一種注釋。以下幾個例子就是最好的說明:
y=p+i-c;
和
YearlySum=Principal+Interest-Charges:
哪一個更清楚呢?
p=*(l+o);
和
page=&List[offset];
哪一個更清楚呢?