Annotation of mstools/mfc/doc/tn012.txt, revision 1.1.1.1

1.1       root        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.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.