Annotation of mstools/mfc/doc/tn012.txt, revision 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.