home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK11 / MFC / DOC / TN012.TX$ / tn012
Encoding:
Text File  |  1992-03-18  |  10.3 KB  |  216 lines

  1.  
  2. Microsoft Foundation Classes                           Microsoft Corporation
  3. Technical Notes
  4.  
  5. #12 : Using MFC with Windows 3.1 Robustness Features
  6.  
  7. Windows 3.1 is a major improvement over Windows 3.0 in the
  8. area of robust application development.  Windows 3.1 includes
  9. a number of new features that enhance the reliability of a
  10. Windows application.  This technical note describes the
  11. use of these features within the MFC library.
  12.  
  13. =============================================================================
  14.  
  15. Windows 3.1 Debug Kernel
  16. ========================
  17.  
  18. Testing your MFC application with the debug system executables is probably
  19. the best thing you can do to make sure your applications are robust
  20. and reliable.  The debugging versions of the system executables perform all
  21. sorts of useful error checking for you, informing you of any problems
  22. that arise with debug output messages.
  23.  
  24. The best way to use the debug system is with two machines: a machine for
  25. testing and debugging that has the debug system installed, and a machine for
  26. development.  If you put a monochrome adapter card in your debug machine,
  27. CodeView and debug system output can be directed to the monochrome monitor.
  28.  
  29. But, not everyone can afford to buy a second machine just for debugging. One
  30. drawback of installing the debug system on your development machine is that
  31. it runs somewhat slower than the standard Windows system, so it slows down
  32. your compiler, editor, and other debugging tools.
  33.  
  34. A useful trick for single-machine debugging is to place copies of the system
  35. and debug binaries and symbols in a separate directory, and have batch files
  36. that copy the appropriate files to your Windows System directory.  This way
  37. you can exit Windows and switch back and forth quickly between debug and
  38. non-debug.  The SDK installation program will set this up for then you can
  39. switch between debug and nondebug version of Windows with the D2N.BAT and 
  40. N2D.BAT batch files.
  41.  
  42. If you aren't running with a debugger or a debug terminal, you should run the
  43. DBWIN application so you can see the error and warning messages produced by
  44. the debug system.  This application is included with the SDK.
  45.  
  46. Here are some common programming errors that appear more frequently than they
  47. should in shipped Windows applications.  Many of these problems can cause
  48. random system UAEs and other problems under Windows 3.0.  The debug system 
  49. binaries will help you track down these kinds of problems very quickly:
  50.  
  51.     * Passing invalid parameters of all shapes and sizes
  52.  
  53.     * Accessing nonexistent window words.  In 3.0, a SetWindowWord or
  54.       SetWindowLong call past the end of the allocated window words (as
  55.       defined with RegisterClass) would trash internal window manager data
  56.       structures!
  57.  
  58.     * Using handles after they've been deleted or destroyed
  59.  
  60.     * Using a DC after it has been released
  61.  
  62.     * Deleting GDI objects before they're deselected from a DC
  63.  
  64.     * Forgetting to delete GDI bitmaps, brushes, pens, or other GDI
  65.       or USER objects when an application terminates
  66.  
  67.     * Writing past the end of an allocated memory block
  68.  
  69.     * Reading or writing through a memory pointer after it has been freed
  70.  
  71.     * Forgetting to export window procedures and other callbacks
  72.  
  73.     * Forgetting to use MakeProcInstance with dialog procs and other
  74.       callbacks (alternatively, you can use the MS C/C++ 7.0 feature
  75.       of marking these functions as EXPORT in their declaration.)
  76.  
  77.     * Shipping an app without running it with the debugging KERNEL, USER,
  78.       and GDI.
  79.  
  80.  
  81. MFC Diagnostics
  82. ===============
  83.  
  84. In addition, the Microsoft Foundation Classes ship with a 
  85. set of robustness features that are compiled and linked only in the
  86. debug build of the library (those library variants ending with a 'd'.)
  87. Use of these features in the applications you write and in the
  88. classes you design will greatly improve both the runtime and
  89. compile time error trapping of your application.  These functions
  90. are outlined below, but all are documented in the Class Library
  91. Reference manual.
  92.  
  93. Every class in MFC includes a class invariant, AssertValid.  This
  94. member function is called to verify the "sanity" of a C++ object.  
  95. You call use this function whenever objects (or pointers or
  96. references to objects) are passed as parameters.  The macro
  97. ASSERT_VALID(pObject) is supplied so that these calls are not
  98. compiled for retail builds.  Your class' implementation of this
  99. function should first call the base class AssertValid explicitly
  100. before doing any derived class specific validation.
  101.  
  102. Parameter validation is another important feature.  Aside from
  103. validating objects, it is also important to validate buffers
  104. and string constants.  The global function AfxIsValidAddress should
  105. be used to verify the validity of a buffer/length pair.  The
  106. Class Library Reference provides you with specific information
  107. on this API.
  108.  
  109. Every class in MFC implements a Dump member function, which
  110. permits you to view the state of an object in an ASCII format.  This
  111. function can be called from CodeView or placed within #ifdef _DEBUG
  112. /#endif portions of your code.  You should supply a Dump member
  113. for classes that you implement.  As with AssertValid, you should
  114. first explicitly call your base class Dump member function.  The
  115. output of Dump is routed to the "afxDump" CDumpContext which 
  116. by default goes to the CodeView output window or to your debug 
  117. terminal.  You can also use the DBWIN program to view the output of 
  118. afxDump.  The source file \C700\MFC\SRC\DUMPINIT.CPP includes information 
  119. on how to route afxDump to another destination.
  120.  
  121. TRACE is a macro that behaves much like printf, only routes
  122. output to the afxDump location.  You should use TRACE statements
  123. to indicate tricky or exceptional places in your code.  As with
  124. other robustness features, TRACE is only meaningful in the
  125. debug library, and has no affect in the retail build.  The MFC library
  126. includes a number of built in TRACE statements for tracking the
  127. flow of messages.  Please see TN007.TXT for more information of
  128. the debug trace information.
  129.  
  130. ASSERT is a runtime check for the validity of a statement.  You
  131. should use ASSERTs liberally throughout your program.  Any place
  132. you have a comment to the affect:
  133.     /* lpStr should be NULL at this point */
  134. you should replace that with a runtime assert:
  135.     ASSERT(lpStr == NULL);
  136. The compiler cannot understand English, but it can execute
  137. code!  ASSERT statements have no affect in retails builds.  If
  138. you need the side effects of an ASSERT to occur in the retail build
  139. as well, then use the VERIFY macro.  
  140.  
  141. MFC also includes an extensive diagnostic memory allocator.  You
  142. diagnostic memory allocator to make sure that you free all memory
  143. resources before your program exits.  The diagnostic
  144. allocator will track the source file and line number of an
  145. allocation, so if you use the CMemoryState::DumpAllObjectsSince
  146. API you can locate any remaining allocations.  A good place to
  147. use this API is in the ExitInstance member function of CWinApp
  148. (which you can override, but be sure to call the base class 
  149. ExitInstance.)  Additionally, if you have a rather tricky piece
  150. of code that does lots of allocations and deallocations, you can
  151. use the CMemoryState::Checkpoint and CMemoryState::Difference
  152. APIs to be sure to leave the world in a steady state after
  153. executing such code.
  154.  
  155.  
  156. Windows 3.1 STRICT type checking
  157. ================================
  158.  
  159. STRICT type checking is an option available with the new
  160. WINDOWS.H header file.  Before a discussion of the use
  161. of STRICT, a brief description of C++ typesafe linkage is
  162. in order.
  163.  
  164. In C++ you are permitted to have many functions with the
  165. same name, so long as these functions have different formal
  166. parameter lists.  In order to have unique link symbols, the
  167. C++ compiler will "decorate" these names using an algorithm
  168. that encodes information about a function such as the name,
  169. number and type of formal parameters, calling convention, etc.
  170. This newly generated name is used as the external link symbol
  171. for the function.  This is known as typesafe linkage and is a 
  172. big benefit of C++.  This name decoration does not apply to
  173. functions within an extern "C" block, and is why all APIs in
  174. WINDOWS.H are in such a block.
  175.  
  176. STRICT typechecking in WINDOWS.H attempts to imitate C++ type
  177. safety for C by using distinct types to represent all the different
  178. HANDLES in Windows.  So for example, STRICT prevents you from
  179. mistakenly passing an HPEN to a routine expecting an HBITMAP.
  180. Since the Windows APIs are all within extern "C" { } blocks,
  181. they are not decorated in the manner described above.  STRICT
  182. plays tricks with the C compiler by changing the types of
  183. the various Windows typedefs to make them unique (specifically
  184. it uses different pointer types to represent HANDLEs, which cannot
  185. be freely converted without an explicit cast.)
  186.  
  187. As you can see, if you have STRICT typechecking enabled in
  188. one file, but not in another, the C++ compiler will generate
  189. different external link symbols for a single function.  This
  190. will result in link time errors.  Therefore, it is recommended
  191. that you use STRICT typechecking only for C modules (those that
  192. end in .C).  Additionally, STRICT is a compile time only
  193. option, so once you sucessfully compile your code the benefits
  194. of STRICT are completely realized.
  195.  
  196. MFC accomplishes all of STRICT static typechecking, plus a whole
  197. lot more, by using the C++ language.  Therefore, STRICT is disabled
  198. by default.  If you wish to use STRICT you will need to recompile
  199. the MFC libraries that you regularly use (because of typesafe
  200. linkage, the external link symbols are different between STRICT
  201. and non-STRICT.)
  202.  
  203. The following are guidelines for using STRICT with C/C++/MFC.
  204.  
  205. If you have existing Windows 3.0 C code and you wish to keep it as C code,
  206. you can either work to make it STRICT compliant or not, that option is
  207. yours.  Be sure to use C++ conventions for your exported header file
  208. such as putting extern "C" { } around your C APIs if you intend on
  209. using the header file within any C++ code.  If you have existing Windows
  210. 3.1 STRICT C code, then moving it to C++/MFC eliminates the need for
  211. STRICT.  
  212.  
  213. For any C code that you have, the use of STRICT is optional
  214. and encouraged.  For C++ code, you should use STRICT with
  215. great care, if at all, because of the issues of typesafe linkage.
  216.