• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            今天遇到一個比較有意思的bug, 這里簡單記錄下。

            Bug的癥狀是通過拖拉邊框把我們客戶端主窗口拖小之后,再最大化,會發現窗口顯示有問題, 看起來像是刷新問題, 有些地方顯示的不對了。
            這里要說明的是我這里的主窗口是非常復雜的窗口, 里面集成了很多組件(cpmponent),有很多層的子窗口。 這個問題只有在特定條件下才會發生, 正常情況下都是好的。

            遇到這種問題,我們怎么處理? 

            首先當然是觀察癥狀, 究竟是刷新問題, 還是Layout出錯了。
            我們可以通過Spy++查看窗口層次是不是正確, 窗口位置是不是對的。
            查看結果是窗口的層次和Layout位置都沒有問題。

            既然我們這里遇到的刷新問題,所以我們要從WM_PAINT消息著手, 我們通過Spy++查看相關窗口的WM_PAINT是不是正確。
            很快我們就會發現某個窗口正在不停地收到WM_PAINT消息, 很可能與我們的bug有關。

            一個窗口不停的收到WM_PAINT重畫, 無非大概有幾類原因:
            正常情況是我們正在做動畫, 可能是通過定時器之類的東西讓窗口不停地InvalidateRect重畫某塊區域, 我們的窗口明顯不屬于這種情況。
            異常情況有時是WM_PAINT消息里我們的消息處理函數在某些條件下直接返回了,從而沒有調用BeginPaint告訴窗口無效區域已經有效, 這樣會因為因為窗口一直有無效區域存在,導致窗口一直收到WM_PAINT消息。
            還有一種異常情況情況是我們是在WM_PAINT消息里調用BeginPaint后又調用了InvalidateRect, 這樣會導致窗口后面會再次收到WM_PAINT消息, 最后窗口陷入WM_PAINT的死循環。 

            那么我們這里的問題窗口屬于哪類? 用什么方法可以判斷出來?

            注意到這里關鍵的三個API:BeginPaint, EndPaint, InvalidateRect的第一個參數都是窗口句柄, 我們可以通過WinDbg的API斷點來跟蹤執行過程, Attach WinDbg到我們的主窗口進程,比如我們的窗口句柄是0x209A0, 我們可以這樣設置API斷點:
            bp USER32!NtUserInvalidateRect ".if(dwo(@esp+0x4)==0x209A0) {kv;gc} .else {gc}"
            bp USER32!NtUserBeginPaint ".if(dwo(@esp+0x4)==0x209A0) {kv;gc} .else {gc}"
            bp USER32!NtUserEndPaint ".if(dwo(@esp+0x4)==0x209A0) {kv;gc} .else {gc}"
            上面的條件斷點表示,當調用我們的對應的API,并且第一個參數(窗口句柄)是我們的目標窗口時,打印堆棧。

            很快我定位出Bug發生的原因了, 條件斷點顯示了API如下的調用次序:
            BeginPaint->InvalidateRect->InvalidateRect->EndPaint
            找到Bug的原因后,然后把Bug assign給該模塊的負責人。 (看我夠意思吧,不僅找到原因,還把調用棧都提供了)

            另外 ,后面還發現這個bug發生時窗口的某些行為會不對, 測試發現原因是所有窗口的定時器都不能正常工作了。
            關于這個問題, 你能想到原因嗎? 

            如果想不到, 請把我的這篇博客《從點擊Button到彈出一個MessageBox, 背后發生了什么》看一遍。
            如果看了還想不到, 重點看第4條。

            最后, 簡單總結下:計算機的好處是它永遠不會欺騙你, 它只會按部就班的執行, 所以很多看似奇怪(甚至看似不可思議的問題), 只要你理解了程序背后的機制原理,都是可以找出根本原因的。
            posted on 2014-05-30 23:18 Richard Wei 閱讀(2686) 評論(2)  編輯 收藏 引用 所屬分類: windbg

            FeedBack:
            # re: 記一個界面刷新相關的Bug
            2014-06-04 09:59 | friv 3
            我將收藏此頁,并與他的幾個朋友一起分享,希望他們能有所幫助。感謝分享。
            http://www.friv3go.com  回復  更多評論
              
            # re: 記一個界面刷新相關的Bug
            2014-06-22 20:52 | 旗袍女裝
            所以很多看似奇怪(甚至看似不可思議的問題), 只要你理解了程序背后的機制原理,都是可以找出根本原因的。旗袍女裝www.ssnz88.net  回復  更多評論
              
            久久精品中文无码资源站| 77777亚洲午夜久久多喷| 久久99国产精品二区不卡| 久久国产免费观看精品| 久久久久亚洲精品中文字幕| 香港aa三级久久三级老师2021国产三级精品三级在| 欧美性大战久久久久久| 国产美女久久精品香蕉69| 久久人人超碰精品CAOPOREN| 久久亚洲精品国产精品| 久久久久久极精品久久久| 浪潮AV色综合久久天堂| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 国内精品综合久久久40p| 精品久久久久久国产潘金莲| 亚洲色欲久久久久综合网| 久久国产乱子精品免费女| 久久久久亚洲精品日久生情| 久久婷婷久久一区二区三区| 欧洲精品久久久av无码电影| 亚洲国产高清精品线久久| 久久亚洲国产精品一区二区| 久久综合噜噜激激的五月天| 久久精品中文字幕大胸| 国内精品久久久久久不卡影院| 亚洲精品国产字幕久久不卡| 欧美日韩中文字幕久久久不卡| 91久久国产视频| 99久久人人爽亚洲精品美女| 久久精品国产99久久无毒不卡| 亚洲午夜久久久久久噜噜噜| 久久综合久久综合亚洲| 日本高清无卡码一区二区久久| 国产综合成人久久大片91| 久久精品视频网| 色综合合久久天天综合绕视看| 久久精品国产精品亚洲精品| 国产91色综合久久免费| 91精品国产91久久久久福利| 久久精品人人做人人爽电影蜜月| 久久久久亚洲Av无码专|