⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfc10.php

📁 php网页版的mfc教程 不是十分详细 但是很精练 我是新手不是十分会欣赏
💻 PHP
📖 第 1 页 / 共 2 页
字号:
  <P align=justify>使用ASSERT断言判定程序是否可以继续执行。</P>
  <P align=justify>TRACE</P>
  <P 
  align=justify>使用TRACE宏显示或者打印调试信息。TRACE是通过函数AfxTrace实现的。由于AfxTrace函数使用了cdecl调用约定,故可以接受个数不定的参数,如同printf函数一样。它的定义和实现如下:</P>
  <P align=justify>void AFX_CDECL AfxTrace(LPCTSTR lpszFormat, ...)</P>
  <P align=justify>{</P>
  <P align=justify>#ifdef _DEBUG // all AfxTrace output is controlled by 
  afxTraceEnabled</P>
  <P align=justify>if (!afxTraceEnabled)</P>
  <P align=justify>return;</P>
  <P align=justify>#endif</P>
  <P align=justify></P>
  <P align=justify>//处理个数不定的参数</P>
  <P align=justify>va_list args;</P>
  <P align=justify>va_start(args, lpszFormat);</P>
  <P align=justify></P>
  <P align=justify>int nBuf;</P>
  <P align=justify>TCHAR szBuffer[512];</P>
  <P align=justify></P>
  <P align=justify>nBuf = _vstprintf(szBuffer, lpszFormat, args);</P>
  <P align=justify>ASSERT(nBuf &lt; _countof(szBuffer));</P>
  <P align=justify></P>
  <P align=justify>if ((afxTraceFlags &amp; traceMultiApp) &amp;&amp; 
  (AfxGetApp() != NULL))</P>
  <P align=justify>afxDump &lt;&lt; AfxGetApp()-&gt;m_pszExeName &lt;&lt; ": 
  ";</P>
  <P align=justify>afxDump &lt;&lt; szBuffer;</P>
  <P align=justify></P>
  <P align=justify>va_end(args);</P>
  <P align=justify>}</P>
  <P align=justify>#endif //_DEBUG</P>
  <P align=justify></P>
  <P 
  align=justify>在程序源码中,可以控制是否显示跟踪信息,显示什么跟踪信息。如果全局变量afxTraceEnabled为TRUE,则TRACE宏可以输出;否则,没有TRACE信息被输出。如果通过afxTraceFlags指定了跟踪什么消息,则输出有关跟踪信息,例如为了指定“Multilple 
  Application Debug”,令AfxTraceFlags|=traceMultiApp。可以跟踪的信息有:</P>
  <P align=justify>enum AfxTraceFlags</P>
  <P align=justify>{</P>
  <P align=justify>traceMultiApp = 1, // multi-app debugging</P>
  <P align=justify>traceAppMsg = 2, // main message pump trace (includes 
DDE)</P>
  <P align=justify>traceWinMsg = 4, // Windows message tracing</P>
  <P align=justify>traceCmdRouting = 8, // Windows command routing trace </P>
  <P align=justify>//(set 4+8 for control notifications)</P>
  <P align=justify>traceOle = 16, // special OLE callback trace</P>
  <P align=justify>traceDatabase = 32, // special database trace</P>
  <P align=justify>traceInternet = 64 // special Internet client trace</P>
  <P align=justify>};</P>
  <P 
  align=justify>这样,应用程序可以在需要的地方指定afxTraceEnabled的值打开或者关闭TRACE开关,指定AfxTraceFlags的值过滤跟踪信息。</P>
  <P align=justify>Visual C++提供了一个TRACE工具,也可以用来完成上述功能。</P>
  <P align=justify></P>
  <P 
  align=justify>为了显示消息信息,MFC内部定义了一个AFX_MAP_MESSAG类型的数组allMessages,储存了Windows消息和消息名映射对。例如:</P>
  <P align=justify>allMessages[1].nMsg = WM_CREATE,</P>
  <P align=justify>allMessages[1].lpszMsg = “WM_CREATE”</P>
  <P 
  align=justify>MFC内部还使用函数_AfxTraceMsg显示跟踪消息,它可以接收一个字符串和一个MSG指针,然后,把该字符串和MSG的各个域的信息组合成一个大的字符串并使用AfxTrace显示出来。</P>
  <P align=justify>allMessages和函数_AfxTraceMsg的详细实现可以参见AfxTrace.cpp。</P>
  <P align=justify></P>
  <LI>MFC对象内容转储 
  <P></P>
  <P 
  align=justify>对象内容转储是CObject类提供的功能,所有从它派生的类都可以通过覆盖虚拟函数DUMP来支持该功能。在讲述CObject类时曾提到过。</P>
  <P align=justify>虚拟函数Dump的定义:</P>
  <P align=justify>class ClassName : public CObject</P>
  <P align=justify>{</P>
  <P align=justify>public:</P>
  <P align=justify>#ifdef _DEBUG</P>
  <P align=justify>virtual void Dump( CDumpContext&amp; dc ) const;</P>
  <P align=justify>#endif</P>
  <P align=justify>…</P>
  <P align=justify>};</P>
  <P 
  align=justify>在使用Dump时,必须给它提供一个CDumpContext类型的参数,该参数指定的对象将负责输出调试信息。为此,MFC提供了一个预定义的全局CDumpContext对象afxDump,它把调试信息输送给调试器的调试窗口。从前面AfxTrace的实现可以知道,MFC使用了afxDump输出跟踪信息到调试窗口。</P>
  <P align=justify>CDumpContext类没有基类,它提供了以文本形式输出诊断信息的功能。</P>
  <P align=justify>例如:</P>
  <P align=justify>CPerson* pMyPerson = new CPerson;</P>
  <P align=justify>// set some fields of the CPerson object...</P>
  <P align=justify>//...</P>
  <P align=justify>// now dump the contents</P>
  <P align=justify>#ifdef _DEBUG</P>
  <P align=justify>pMyPerson-&gt;Dump( afxDump );</P>
  <P align=justify>#endif</P>
  <P align=justify></P>
  <LI>MFC对象有效性检测 
  <P></P></LI></OL>
<P 
align=justify>对象有效性检测是CObject类提供的功能,所有从它派生的类都可以通过覆盖虚拟函数AssertValid来支持该功能。在讲述CObject类时曾提到过。</P>
<P align=justify>虚拟函数AssertValid的定义:</P>
<P align=justify>class ClassName : public CObject</P>
<P align=justify>{</P>
<P align=justify>public:</P>
<P align=justify>#ifdef _DEBUG</P>
<P align=justify>virtual void AssertValid( ) const;</P>
<P align=justify>#endif</P>
<P align=justify>… </P>
<P align=justify>};</P>
<P 
align=justify>使用ASSERT_VALID宏判断一个对象是否有效,该对象的类必须覆盖了AssertValid函数。形式为:ASSERT_VALID(pObject)。</P>
<P align=justify>另外,MFC提供了一些函数来判断地址是否有效,如:</P>
<P align=justify>AfxIsMemoryBlock,AfxIsString,AfxIsValidAddress。</P>
<OL>
  <OL>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445889128></A><A name=_Toc445782531></A><A 
      name=_Toc452640990></A><A name=_Toc457299099></A><B>内存诊断</B> 
      <P></P></LI></OL></OL></OL>
<P align=justify>MFC使用DEBUG_NEW来跟踪内存分配时的执行的源码文件和行数。</P>
<P align=justify>把#define new DEBUG_NEW插入到每一个源文件中,这样,调试版本就使用_malloc_dbg来分配内存。MFC 
Appwizard在创建框架文件时已经作了这样的处理。</P>
<OL>
  <P align=justify>
  <LI>AfxDoForAllObjects 
  <P></P>
  <P align=justify>MFC提供了函数AfxDoForAllObjects来追踪动态分配的内存对象,函数原型如下:</P>
  <P align=justify>void AfxDoForAllObjects( void (*pfn)(CObject* pObject, </P>
  <P align=justify>void* pContext), void* pContext ); </P>
  <P align=justify>其中:</P>
  <P align=justify>参数1是一个函数指针,AfxDoForAllObjects对每个对象调用该指针表示的函数。</P>
  <P align=justify>参数2将传递给参数1指定的函数。</P>
  <P 
  align=justify>AfxDoForAllObjects可以检测到所有使用new分配的CObject对象或者CObject类派生的对象,但全局对象、嵌入对象和栈中分配的对象除外。</P>
  <P align=justify></P>
  <LI>内存漏洞检测 
  <P></P></LI></OL>
<P align=justify>仅仅用于new的DEBUG版本分配的内存。</P>
<P align=justify>完成内存漏洞检测,需要如下系列步骤:</P>
<UL>
  <P align=justify>
  <LI>调用AfxEnableMemoryTracking(TRUE/FALSE)打开/关闭内存诊断。在调试版本下,缺省是打开的;关闭内存诊断可以加快程序执行速度,减少诊断输出。 

  <P></P>
  <P align=justify></P>
  <LI>使用MFC全局变量afxMemDF更精确地指定诊断输出的特征,缺省值是allocMemDF,可以取如下值或者这些值相或: 
  <P></P></LI></UL>
<P align=justify>afxMemDF,delayFreeMemDF,checkAlwaysMemDF</P>
<P 
align=justify>其中:allocMemDF表示可以进行内存诊断输出;delayFreeMemDF表示是否是在应用程序结束时才调用free或者delete,这样导致程序最大可能的分配内存;checkAlwaysMemDF表示每一次分配或者释放内存之后都调用函数AfxCheckMemory进行内存检测(AfxCheckMemory检查堆中所有通过new分配的内存(不含malloc))。</P>
<P align=justify>这一步是可选步骤,非必须。</P>
<UL>
  <P align=justify>
  <LI>创建一个CMemState类型的变量oldMemState,调用CMemState的成员函数CheckPoint获得初次内存快照。 
  <P></P>
  <P align=justify></P>
  <LI>执行了系列内存分配或者释放之后,创建另一个CMemState类型变量newMemState,调用CMemState的成员函数CheckPoint获得新的内存快照。 

  <P></P>
  <P align=justify></P>
  <LI>创建第三个CMemState类型变量difMemState,调用CMemState的成员函数Difference比较oldMemState和newMemState,结果保存在变量difMemState中。如果没有不同,则返回FALSE,否则返回TRUE。 

  <P></P>
  <P align=justify></P>
  <LI>如果不同,则调用成员函数DumpStatistics输出比较结果。 
  <P></P></LI></UL>
<P align=justify>例如:</P>
<P align=justify>// Declare the variables needed</P>
<P align=justify>#ifdef _DEBUG</P>
<DIR>
<P align=justify>CMemoryState oldMemState, newMemState, diffMemState;</P>
<P align=justify>oldMemState.Checkpoint();</P></DIR>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>// do your memory allocations and deallocations...</P>
<P align=justify>CString s = "This is a frame variable";</P>
<P align=justify>// the next object is a heap object</P>
<P align=justify>CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );</P>
<P align=justify></P>
<P align=justify>#ifdef _DEBUG</P>
<DIR>
<P align=justify>newMemState.Checkpoint();</P>
<P align=justify>if( diffMemState.Difference( oldMemState, newMemState ) )</P>
<P align=justify>{</P>
<DIR>
<P align=justify>TRACE( "Memory leaked!\n" );</P>
<P align=justify>diffMemState.DumpStatistics();</P>
<P align=justify>//or diffMemState.DumpAllObjectsSince();</P></DIR>
<P align=justify>}</P></DIR>
<P align=justify>#endif</P>
<P align=justify>MFC在应用程序(调试版)结束时,自动进行内存漏洞检测,如果存在漏洞,则输出漏洞的有关信息。</P>
<hr>
<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
  <tr>
    <td align="center"><a href="mfc9.php" target="_self">上一章</a> <a href="mfc.php" target="_self">回目录</a> <a href="mfc11.php" target="_self">下一章</a></td>
  </tr>
</table>
<p>&nbsp;</p>
<P align=justify></P>
</BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -