八宝书库 > 文学其他电子书 > 深入浅出MFC第2版(PDF格式) >

第182部分

深入浅出MFC第2版(PDF格式)-第182部分

小说: 深入浅出MFC第2版(PDF格式) 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




                                              附錄D    以MFC 重建DBWIN  



    附錄D 



               以MFC 重建 DBWIN 



     洠в小 BWIN  ,TRACE  唱什麼獨角戲?Visual C++  的  TRACE  字串輸出必須在整合環境的除錯視 



     窗看到。這太過份了。我們只不過想在射擊撸穲鐾嫱妫④泤s要我們扛尊  155  加農砲。 



                                      侯俊傑 

                                             /  1997。01 發表於Run!PC 雜誌 



     我自己常喜歡在程式加個  printf  ,觀察程式的流程或變數的內容。簡簡單單,不必驚動除 



     錯器之類的大傢伙。 



printf  AfxMessageBox           TRACE 

      、                     與 



     printf     C                       text mode     Windows  

         是  語言的標準函式,但只能在文字模式(                 )執行。         圖形介 



     面差可比擬的是  AfxMessageBox  ,可以輕輕鬆鬆在對話盒列印出你的字串。然而 



     AfxMessageBox                                  OK 

               有個缺點:它會打斷程式的行進,非得使用者按【  】按鈕不可。再 



     者,如果  AfxMessageBox  對話盒畫面侵佔了原程式的視窗畫面,旦對話盒結束,系統 



                           WM PAINT               OnDraw 

                              _          View            

     會對程式視窗發出原本不必要的                ,於是      類別的         會被呼叫。如 



     果你的  AfxMessageBox  正是放在  OnDraw  函式,這惡性循環可有得瞧了。 



     TRACE  洠в羞@種缺點,它的輸出集到個特定視窗,它不會打斷你測試程式的雅 



                                                                      921 


…………………………………………………………Page 984……………………………………………………………

               第五篇    附錄  



                                                         OK 

               興,不會在你全神貫注思考程式邏輯時還要你分神來按【  】鈕。更重要的是,它不會 



               干擾到程式的視窗畫面。 



               Visual C++ 1。5  時代,TRACE  的字串輸出是送到個名為  DBWIN  的視窗。你可以 



                                      TRACE                            Visual C++ 

               邊執行程式,邊即時觀察其               輸出。許多早已發現件不幸的事實: 



               4。x  之洠в小 BWIN  ,生活的步眨虼藖y了,寫程式的生命有些狼狽不堪。 



                     DBWIN TRACE           Visual C++    TRACE  

               洠в小       。     〕颤N獨角戲?             的       字串輸出必須在整合環境 



               的除錯視窗看到。TRACE  巨集只在除錯模式的程式碼才能生效,而  Visual C++  竟 



               還要求程式必須在整合環境的除錯器內執行,內含的  TRACE  巨集才有效。這太過份了。 



               我只不過想在撸穲鐾纥c射擊撸颍麄儏s要我扛尊  155  加農砲來。不少朋友都對這 



               種情況相當不滿。 



          Paul DiLascia 



               Microsoft Systems Journal MSJ               TRACE  

                                  (  )的兩篇文章,彌補了                的這點小小遺憾: 



               第篇文章出現在  MSJ  1995。10  的  C/C++  專欄,第篇文章出現在  MSJ  1996。01  的 



               C/C++  專欄。兩篇都出自  Paul DiLascia  之手,這位先生在  C++ / MFC  享有盛名,著有 



                Windows++  書。 



               Paul  DiLascia  發明了種方法,讓你的  TRACE  巨集輸出到個視窗(他把它命名為 



               Tracewin  視窗),這個視窗就像  Visual C++ 1。5  的  DBWIN  樣,可以收集來自八方的 



               TRACE  字串,可以把內容清除,或存檔,或做其他任何文字編輯的處理。你的程式只 



               要是除錯模式就行。至於除錯器,把它丟開,至少在這個時刻。 



               我將在這篇文章敘述  Paul DiLascia  的構想和作法,並引用部份程式碼。完整程式碼可 



                     MSJ    ftp site ftp。microsoft。    MSDN  Microsoft Developer's 

               以從       的     (            )免費載,也可以從          ( 



               Network )光碟片獲得。 



               此法富有巧思,可以豐富我們的  MFC  技術經驗。所有榮耀都屬於作者  Paul DiLascia 。 



922 


…………………………………………………………Page 985……………………………………………………………

                                               附錄D    以MFC 重建DBWIN  



     我呢,我只是向大家推耍K介紹這兩篇文章、這個、這個好工具,並且儘量豐富稍嫌 



     簡陋的兩篇原文。當文章使用第稱來描述  Tracewin  的程式設計理念時,那個「我」 



     代表的是  Paul DiLascia  而不是侯俊傑。 



擒偾芡酢



     要把  TRACE  的輸出字串導向,得先明白  TRACE  巨集到底是怎麼回事。TRACE  事實 



          Win32 API  OutputDebugString                hooking Win32 API 

     呼叫了          函式              。好,可能你會想到以類似 



     的作法,把  OutputDebugString  函式導到你的某個函式來,再予取予求。這種方法在 



     Windows  NT             Windows  NT    copy…on…write  裕А

               不能湊效,因為               的           分頁機制( )使得我 



               OutputDebugString                 OutputDebugString  

     旦修改了                 ,我就擁有了份屬於自己的                     副本。 



     我可以高高興興盡情使用這副本(渾然不覺),但其他程式呼叫的卻仍然是那未經 



     雕琢的,身處KRNL386  模組的  OutputDebugString 。這樣就洠в惺颤N大用處啦! 



             copy…on…write  Matt Pietrck  Windows 95 System Programming SECRETS 

     裕В核^            機制,          的 



     第5章(#290  頁)解釋得相當好。我大略說明它的意義。 



     當作業系統極儘可能共享程式碼,對除錯器會帶來什麼影響?如果除錯器寫入斷點 



     指令的那個  code  page  是被兩個行程共享的話,就會有潛在問睿R溃e器只對 



     個行程除錯,另個行程即使碰到斷點,也不應該受影響。 



     高級作業系統對付此問睿姆椒ㄊ撬^的  〃copy on write〃  機制:記憶體管理器使用  CPU 



     的分頁機制,儘可能將記憶體共享出來,而在必要的時候又將某些  RAM  page  眩u 



     份。 



                        instance                  code  pages 

     假設某個程式的兩個個體(             )都正在執行,共享相同的               (都是唯讀性 



     伲F渲庫冻e狀態,使用者告訴除錯器在程式某處放個斷點 



       breakpoint                              page fault   code page  

      (       )。當除錯器企圖寫入斷點指令,會樱l個                 (因為         擁 



     有唯讀屬性)。作業系統看到這個page fault  ,首先斷定是除錯器企圖讀記憶體內容, 



     這是合法的。然而,隨後寫入到共享記憶體的動作就不被允許了。系統於是會先將受 



     影響的各頁拷貝份,並改變被除錯者的  page table  ,使映射關係轉變到這份拷貝版。 



     旦記憶體被拷貝並被映射,系統就可以讓寫入動作過關了。寫入動作只影響拷貝內容, 



                                                                       923 


…………………………………………………………Page 986……………………………………………………………

                   第五篇    附錄  



                   不影響原先內容。 



                   Copy on write  機制的最大好處就是儘可能讓記憶體獲得共享效益。只有在必要時刻,系 



                   統才會對共享記憶體做出新的拷貝。 



                       MFC                                   TRACE                      afxDump 

                   在       程式,所有的詳嘀噶罨蚓藜òā                      。┦聦嵍剂鹘泜名為 



                   的物件之,那是個                  CDumpContext  物件。所有的詳鄤幼鞫歼M入 



                   CDumpContext::OutputString  成員函式,然後才進入全域函式  AfxOutputDebugString         ,把 



                   字串送往除錯器。 



                   攔截除錯器是很困難的啦,但是你知道,字串也可以被送往檔案。如果我們能夠把送往 



                   檔案的字串攔截來,大功就完成了半。這個通往檔案的奧秘在哪裡呢?看看  MFC  的 



                           圖一                           m_pFile                          m_pFile 

                   原始碼(        )。啊哈,我們發現,如果                    有所指定,字串就流往檔案。 



                   是個  CFile  物件(圖二)。 



                   // in MFC 4。x DUMPCONT。CPP 

                   #0001  void CDumpContext::OutputString(LPCTSTR lpsz) 

                   #0002  { 

                   #0003  #ifdef _DEBUG 

                   #0004      // all CDumpContext output is controlled by afxTraceEnabled 

                   #0005      if (!afxTraceEnabled) 

                   #0006          return; 

                   #0007  #endif 

                   #0008 

                   #0009      // use C…runtime/OutputDebugString when m_pFile is NULL 

                   #0010      if (m_pFile == NULL) 

                   #0011      { 

                   #0012          AfxOutputDebugString(lpsz); 

                   #0013          return; 

                   #0014      } 

                   #0015 

                   #0016      // otherwise; write the string to the file 

                   #0017      m_pFile…》Write(lpsz; lstrlen(lpsz)*sizeof(TCHAR)); 

                   #0018  } 



                   圖一      CDumpContext::OutputString   原始碼 



924 


…………………………………………………………Page 987……………………………………………………………

                                                           附錄D    以MFC 重建DBWIN  



// in MFC 4。x AFX。H 

#0001  class CDumpContext 

#0002  { 

#0003  。。。 

#0004  public: 

#0005          CFile* m_pFile; 

#0006  }; 



圖二      CDumpContext   原始碼 



                                  CMfxTrace   圖三               CFile 

好,如果我們能夠設計個類別                              (  ),衍生自                ,然後為它設計 



個初始化成員函式,令函式之檢查  afxDump。m_pFile  內容,並且如果是  NULL  ,就將 



它指向我們的新類別,那麼  CDumpContext::OutputString #17  行的  m_pFile…》Write  就會 



                CMfxTrace      Write 

因此指向新類別                     的         函式,於是我們就可以在其予取予求啦。 



注意,theTracer  是個  static  成員變數,需要做初始化動作(請參考深入湷錾钊霚出MFC (侯 

                                                                   深入湷錾钊霚出 



      /  

俊傑 松崗)第2章「靜態成員」節),因此你必須在類別之外的任何方加這行: 



    CMfxTrace CMfxTrace::theTracer; 



#0001  cla

返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的