關於排錯 專注思考,細心觀察,步步為營

2022-01-15 16:19:31 字數 3019 閱讀 1502

時常有朋友發郵件給我,說遇到了乙個什麼什麼奇怪的問題,不知道是怎麼回事,希望我幫忙看看。我基本上每天都會抽出或長或短的時間來回覆這些郵件,不過也經常發現,其實許許多多的問題都完全是有能力自行解決的。在很多時候,我發現許多朋友還缺乏最基本的解決問題,分析問題的方式。其實我在平時工作中也會遇到各種各樣的問題,有時候甚至異常古怪,但是在仔細分析之下,往往都能解決。於是我現在打算談點解決問題的基本方式,希望可以幫到一些朋友。

如果您也有著方面的體會,也可以分享一下,即使是某個簡單案例也是很有幫助的。

要解決問題,首先是要定位問題,配合正確的推理方式,再仔細分析,「動手嘗試」很可能只是驗證推理是否正確的手段而已,其實大部分的情況都可以用思考來得出(或排除)。要定位問題,很重要的一點便是要把概念理清。很多朋友會輕視概念,認為那種「理論」有什麼重要的,最關鍵的是「動手」——但殊不知概念能讓您的「動手」少走很多彎路。

好,既然知道是**內容的問題,那麼接下來就應該比較的是「乙個可以執行的**」和「乙個不能執行的**」究竟有什麼區別。asp.net站點最關鍵的東西便在於web.config,「能夠執行」往往也是web.config來決定的。例如,你有沒有正確配置httpmodule或httphandler。在許多情況下,解決了asp.net站點的web.config,問題也就解決了大半。同樣的情況還會有,為什麼同樣的**(標記)在有的aspx上就能解析成功,有的就不行?那可能是web.config中沒有引入正確的control標記或命名空間造成的。

有朋友可能會說,你知道web.config的那麼多節點是做什麼的,自然容易排錯,我都不知道,怎麼知道問題在**?其實,我也不知道很多東西,但是我會比較。我一開始用vs寫f#程式的時候,都只是用乙個檔案來練習。後來想要用多個模組了,於是就建立新的原始檔。但是我發現,main方法總是說寫在新檔案裡的模組「還沒有定義」,這讓我很困惑。於是乎,我去網上找一些示例——不是普通**片斷,而是一些用vs編輯的小型專案,它們自然是能夠編譯通過的。例如,我拿到了專案a,我就開始比較它和我的寫法究竟有什麼問題——觀察下來沒有任何收穫,我還是覺得我的做法沒有任何問題。於是我嘗試著在a專案中新增我的模組——奇怪,在a的main方法中還是訪問不到新模組——這不是欺負人麼!

於是我進行更深入的比較,比較除了原始檔之外,它的專案設定和我的專案設定有什麼區別——還是沒有!我抱著最後一絲希望,將a專案中的**新增到我的專案中來,編譯,還是失敗!但是看到這個結果,我反而看到了解決問題的曙光。因為我都已經把源**統一了,這樣可能發生錯誤的地方可謂少之又少。剛才我提到,vs將編譯工作交給外部命令執行,對於f#也一樣。於是我就比較專案a和我的專案在編譯時的輸出,終於發現兩者的區別在於呼叫fsc.exe的時候,引數順序不同。f#的編譯器和c#編譯器不同的地方在於,它對原始檔指定的順序是有要求的,只有放在後面檔案中的**才能訪問到前面檔案中定義的內容,反之則不行。這意味著,main方法必須作為最後乙個原始檔存在。但是,vs並沒有提供乙個選項來調整原始檔的順序,既然這樣,那就手動編輯fsproj檔案吧。至此,問題解決。

我被這個問題困擾很久的原因,就是在於我從來沒有去懷疑過f#編譯器對原始檔的指定順序是有要求的。我之前也觀察過fsc.exe的引數,但是並沒有「看出」什麼問題出來。但是,我會和乙個成功的專案慢慢比較,把我的專案和它慢慢靠攏,我用這種方式排除了各種錯誤可能性,最終把我的關注點又「逼迫」到編譯器的引數上。進行比較,嘗試,最終解決問題。再此之前,我也不知道這一點,不是嗎?您其實也一樣,如果遇到了乙個奇怪的問題,沒關係,找乙個成功的案例,詳細比較為什麼它能行而我不行,慢慢地向它靠攏。最終解決問題的時候,就是你獲得新知識的時候。這樣,你的「經驗」增加了。

類似的做法還有:不時有朋友會問到,它的webform專案出現了這樣那樣的問題,例如在postback之後事件沒有執行,狀態沒有恢復,讀不到某個值等等。從我的經驗上來說,這是遇到了生命週期的問題。但是,生命週期是個複雜的玩意兒,除非我親手進行嘗試,我也不可能知道某個特定專案特定問題的解決方案。其實對於這種問題,最好的方法之一,便是從最簡化的模型開始嘗試。例如,您可以準備乙個空白頁面,新增一些控制項和**,執行,成功。然後,您將這個簡單的頁面向您的專案進行靠攏,一次增加一小部分,然後執行看看是否成功。直到某段**新增之後發現失敗了,您就知道到底是什麼原因引起的。可能是新的**有問題,也可能是新**讓之前**的問題暴露出來了。

對於排錯來說,最關鍵的是思考和分析,而不是動手。我有時候見到一些同事在遇到錯誤之後就開始盲目地修改**,重試,最後就算把問題碰對了,時間也浪費了——而且還可能把原有正確的地方改壞了。要進行思考和分析,就要細心觀察,例如您有沒有看清異常的資訊是什麼?有沒有順著innerexception一級一級往下看,看看最終是哪行**出的問題?如今的框架,一般都會把錯誤資訊寫的非常完整。記得之前做wcf的時候,它甚至會告訴你可以嘗試著修改配置中的哪個節點!如果您直接忽視這些,就喪失了第一手資訊了。

還有,別怕英文,就個錯誤資訊而已,沒幾個詞的。

但是我可以這麼說,許多朋友都缺少思考。因為從他們給我的郵件上來看,根本沒有把問題描述清楚。我相信「如果說不清楚,那說明沒想清楚」。事實上,如果能把問題描述清楚了,一般也可以找出用什麼關鍵字去搜尋引擎上查詢資訊。我很奇怪,許多朋友還不會用搜尋引擎,例如他們會對搜尋引擎說很長一句話,而不是提取出中間的「關鍵字」進行查詢。更嚴重的問題是「造詞」。例如「注入」,這個詞很流行啊,指令碼注入,sql注入。於是很多人在提問的時候也一直「注入」,但事實上他的問題和任何一種「現存的注入」的含義都不同。當然,您覺得這是「注入」也沒有關係,但是至少描述一下在您的場景下「注入」是什麼意思,對不對?而且,如果你用「注入」去搜尋引擎上查詢,就會發現基本上找不到你想要的東西,因為「注入」這個詞在網際網路上有別的含義,它和你的含義完全不同,又能給你什麼資訊呢?

此外,查到內容之後,也要進行基本的資訊篩選。例如,一些小站,垃圾站的資訊就不要關心了吧。直接找一些著名的大站,如官方社群,文件,部落格就行了。

最後一點是為我個人而說的。如果您希望讓我分析**,還請把所有可執行的東西打乙個包給我,並告訴乙個略為詳細的步驟,讓我可以直接雙擊開啟編譯執行並重現問題。如果您只給我乙個**片斷,還無法編譯通過,或者還需要我自己去補充各類庫,那我就只能說聲抱歉了。同樣,如果涉及到資料庫,那麼請給乙個用於建立指令碼和測試資料的sql檔案。此外,如果專案太大,最好也新建乙個專案,只放一些核心的東西即可,關鍵在於重現問題。而且就我個人經驗來說,經過「提煉」之後,說不定您自己就已經發現問題所在了。

jeffrey zhao

關於Linux網路排錯

無法連線網路的原因無非是硬體問題或者軟體問題。網線 網線被截斷 網線過渡扭曲變形造成訊號不良 網路接頭與裝置接觸不良。網絡卡,hub及router等網路裝置的問題,常見 的問題如下 網絡卡不穩定,質量不佳,或者與整體系統的相容性不好 各網路裝置的接頭質量不佳,接觸不良,造成訊號衰減 由於網路裝置所處...

關於XUtils框架細解

感謝關注xuitls的最近一段時間給予的熱心反饋,xutils近期做了很多細節優化之後,功能和api已經穩定。1.9.6主要更新內容 bitmap載入動畫有時重複出現的問題修復,載入過程優化 http模組requestcallback等優化。詳細更新記錄見 commits master xutils...

關於專注,關於最近的一些事情

這是自己第一次寫非技術的部落格,但是不寫不行了。最近心情很沉重,因為自己又又又又又一次把事情搞砸了,47個人裡排倒數第二,當看到成績的時候心情真的很壓抑。不止一次開始認認真真的做一件事,然後到一半的時候注意力不夠集中,然後造成一系列的後果。學車的時候,各種公升學考試的時候,軟體設計師考試的時候,求職...