?? appendix.html
字號:
<html><head><title>Writing Bug-Free C Code: Code Listings</title></head><body><center><font size="+3">Appendix A: Code Listings</font><br><a href="index.html">Writing Bug-Free C Code</a><br></center><br><small><a href="#apph">A.1 APP.H Include File</a><br><a href="#bookh">A.2 BOOK.H Include File</a><br><a href="#heapc">A.3 HEAP.C Module</a><br><a href="#randc">A.4 RAND.C Module</a><br><a href="#dosc">A.5 DOS.C Module</a><br><a href="#outputdebugstring">A.6 OutputDebugString() for MS-DOS Programmers</a><br><a href="#reportwinassert">A.7 ReportWinAssert()</a><br></small><br><br>This appendix brings together in one location all the code that was presented in this book. Also available online in a ZIP at <a href="source.zip">http://www.duckware.com/bugfreec/source.zip</a><br><a name="apph"><br></a><big><b>A.1 APP.H Include File</b></big> <br><br>APP.H is a place holder include file that represents the global include file for your application. This is the one include file for all your modules. As you write new modules, you will need to modify this include file. <br><br><table bgcolor="#CCCCEE" cellpadding=0 cellspacing=0><tr><td><pre><b>APP.H</b>/*--- Standard Includes ----------------------------------------*/#include <string.h> /* strcpy/memset */#include <stdio.h> /* sprintf */#include <stdlib.h> /* malloc/free *//*--- The include file for this book ---------------------------*/#include "book.h"/*--- NEWHANDLE section ----------------------------------------*/NEWHANDLE(HRAND);NEWHANDLE(HDOSFH);/*--- USE_* section --------------------------------------------*/#ifdef USE_HRAND/*---------------------------------------------------------------- * * Random number generator * *--------------------------------------------------------------*/EXTERNC HRAND APIENTRY RandCreate ( int );EXTERNC HRAND APIENTRY RandDestroy ( HRAND );EXTERNC int APIENTRY RandNext ( HRAND );#endif#ifdef USE_LOWIO/*-------------------------------------------------------------- * * Access to low-level I/O run-time library functions * *-------------------------------------------------------------*/#include <fcntl.h>#include <sys\types.h>#include <sys\stat.h>#include <io.h>#endif#ifdef USE_HDOSFH/*-------------------------------------------------------------- * * Code wrapper to low-level file I/O * *-------------------------------------------------------------*/EXTERNC HDOSFH APIENTRY DosOpenFile ( LPSTR );EXTERNC WORD APIENTRY DosRead ( HDOSFH, LPVOID, WORD );EXTERNC WORD APIENTRY DosWrite ( HDOSFH, LPVOID, WORD );EXTERNC HDOSFH APIENTRY DosCloseFile ( HDOSFH );#endif</pre></tr></td></table><br>The one include file contains several sections. The first does a general include of string.h, stdio.h and malloc.h. These includes are assumed to be needed by all modules. Next, the include for this book, book.h, is included. <br><br>When programming for Windows, make sure that windows.h is included before book.h gets included and make sure that you are using either /GA (for applications) or /GD (for DLLs) on the Microsoft C8 command line. This ensures that _WINDOWS gets defined. <br><br>The NEWHANDLE section comes next. For every new module that you write, you will need to add a NEWHANDLE(HOBJ) line. The OBJ part is a short descriptive name for the module you are implementing. <br><br>The last section of this file is the USE_* section. For every NEWHANDLE(HOBJ) added to this file, you will also add a #ifdef USE_HOBJ section that prototypes the interface to the new module you have written.<br><a name="bookh"><br></a><big><b>A.2 BOOK.H Include File</b></big> <br><br>BOOK.H is the include file for everything that this book describes. You should never include this file directly. Instead, it should be included through APP.H as described in the previous section. <br><br>BOOK.H assumes that you have a standard C compiler. If you do not have a standard C compiler, you may still be OK if your C preprocessor follows the Reiser model (<a href="chapter2.html#reiserpasting">§2.2.8</a>). The problem is the usage of the stringizing operator (#) and the token pasting operator (##). See <a href="chapter2.html#tokenpasting">§2.2.7</a> for more information on preprocessor operators. <br><br><table bgcolor="#CCCCEE" cellpadding=0 cellspacing=0><tr><td><pre><b>BOOK.H</b>/*--- If target is C8 segmented architecture ---*/#if (defined(_MSC_VER) && defined(MSDOS))#define FAR _far#define NEAR _near#define FASTCALL _fastcall#define PASCAL _pascal#define EXPORT _export#define BASEDIN(seg) _based(_segname(#seg))/*--- Else assume target is flat memory model ---*/#else#define FAR#define NEAR#define FASTCALL#define PASCAL#define EXPORT#define BASEDIN(seg)#endif/*--- size_t mapping ---*/#define SIZET size_t/*--- Useful defines ---*/#ifndef _WINDOWStypedef char FAR*LPSTR;typedef void FAR*LPVOID;typedef unsigned short WORD;typedef int BOOL;#define FALSE (0)#define TRUE (1)#endif/*--- Assert during compiling (not run-time) ---*/#define CompilerAssert(exp) extern char _CompilerAssert[(exp)?1:-1]/*--- TYPEDEF depends upon C/C++ ---*/#ifdef __cplusplus#define TYPEDEF#else#define TYPEDEF typedef#endif/*--- EXTERNC depends upon C/C++ ---*/#ifdef __cplusplus#define EXTERNC extern "C"#else#define EXTERNC#endif/*--- APIENTRY for app/dll ---*/#ifdef _WINDLL#define APIENTRY EXPORT FAR PASCAL#else#define APIENTRY FAR PASCAL#endif/*--- LOCAL/LOCALASM defines ---*/#define LOCAL static NEAR FASTCALL#define LOCALASM static NEAR PASCAL/*--- Other useful defines ---*/#define CSCHAR static char BASEDIN(_CODE)#define NewScope/*--- Absolute value macro ---*/#define ABS(x) (((x)>0)?(x):-(x))/*--- Is a number a power of two ---*/#define ISPOWER2(x) (!((x)&((x)-1)))/*--- Number of static elements in an array ---*/#define NUMSTATICELS(pArray) (sizeof(pArray)/sizeof(*pArray))/*--- Loop Macros ---*/#define LOOP(nArg) { int _nMax=nArg; int loop; \ for (loop=0; loop<_nMax; ++loop)#define LLOOP(lArg) { long _lMax=lArg; long lLoop; \ for (lLoop=0; lLoop<_lMax; ++lLoop)#define ENDLOOP }/*--- WinAssert support ---*/#define USEWINASSERT CSCHAR szSRCFILE[]=__FILE__; \ BOOL static NEAR _DoWinAssert( int nLine ) { \ ReportWinAssert(szSRCFILE, nLine); \ WinAssert(nLine); \ return(FALSE); \ }#define AssertError _DoWinAssert(__LINE__)#define WinAssert(exp) if (!(exp)) {AssertError;} elseEXTERNC void APIENTRY ReportWinAssert( LPSTR, int );/*--- What is a class descriptor---*/typedef struct { LPSTR lpVarName; } CLASSDESC, FAR*LPCLASSDESC;/*--- Declare a new handle ---*/#define NEWHANDLE(Handle) typedef struct tag##Handle *Handle/*--- Class descriptor name from object name ---*/#define _CD(hObj) hObj##_ClassDesc/*--- The class macro ---*/#define CLASS(hObj,Handle) \ static CLASSDESC _CD(hObj)={#hObj}; TYPEDEF struct tag##Handle/*--- Object verification macros---*/#define VERIFY(hObj) WinAssert(_VERIFY(hObj))#define VERIFYZ(hObj) if (!(hObj)) {} else VERIFY(hObj)/*--- Object verification helper macros ---*/#define _S4 (sizeof(LPCLASSDESC))#define _S8 (sizeof(LPCLASSDESC)+sizeof(LPVOID))#define _VERIFY(hObj) \ ( FmIsPtrOk(hObj) && \ (((LPVOID)hObj)==*(LPVOID FAR*)((LPSTR)hObj-_S8)) \ && ((&_CD(hObj))==*(LPCLASSDESC FAR*)((LPSTR)hObj-_S4)) )/*--- Heap manager prototypes ---*/EXTERNC LPVOID APIENTRY FmNew ( SIZET, LPCLASSDESC, LPSTR, int);EXTERNC LPVOID APIENTRY FmFree ( LPVOID );EXTERNC LPVOID APIENTRY FmRealloc ( LPVOID, SIZET, LPSTR, int );EXTERNC LPVOID APIENTRY FmStrDup ( LPSTR, LPSTR, int );EXTERNC void APIENTRY FmWalkHeap ( void );EXTERNC BOOL APIENTRY FmIsPtrOk ( LPVOID );/*--- NEWOBJ() and FREE() Interface ---*/#define _LPV(hObj) *(LPVOID FAR*)&hObj#define NEWOBJ(hObj) \ (_LPV(hObj)=FmNew(sizeof(*hObj),&_CD(hObj),szSRCFILE,__LINE__))#define FREE(hObj) (_LPV(hObj)=FmFree(hObj))/*--- String interface macros ---*/#define NEWSTRING(lpDst,wSize) \ (_LPV(lpDst)=FmNew((SIZET)(wSize),NULL,szSRCFILE,__LINE__))#define MYLSTRDUP(lpDst,lpSrc) \ (_LPV(lpDst)=FmStrDup(lpSrc,szSRCFILE,__LINE__))/*--- Array interface macros ---*/#define NEWARRAY(lpArray, wSize) \ (_LPV(lpArray)=FmNew((SIZET)(sizeof(*(lpArray))*(wSize)), \ NULL,szSRCFILE,__LINE__))#define SIZEARRAY(lpArray, wSize) \ (_LPV(lpArray)=FmRealloc((lpArray), \ (SIZET)(sizeof(*(lpArray))*(wSize)),szSRCFILE,__LINE__))</pre></tr></td></table><br><a name="heapc"><br></a><big><b>A.3 HEAP.C Module</b></big><br><br>This code implements the heap manager as described in<a href="chapter5.html">Chapter 5</a>.<br><br><table bgcolor="#CCCCEE" cellpadding=0 cellspacing=0><tr><td><pre><b>HEAP.C</b>/*pm-------------------------------------------------------------- * * OUTLINE: * * This module REPLACES the memory management routines of * the C run-time library. As such, this new interface * should be used exclusively. * * IMPLEMENTATION: * * A wrapper is provided around all memory objects that * allows for run-time type checking, symbolic dumps of * the heap and validation of heap pointers. * * NOTES: * * - YOU must code an FmIsPtrOk() that works properly for * your environment. * *--------------------------------------------------------------*/#include "app.h"USEWINASSERT/*--- Heap objects are aligned on sizeof(int) boundaries ---*/#define ALIGNMENT (sizeof(int))#define DOALIGN(num) (((num)+ALIGNMENT-1)&~(ALIGNMENT-1))CompilerAssert(ISPOWER2(ALIGNMENT));/*--- Declare what LPPREFIX/LPPOSTFIX are ---*/typedef struct tagPREFIX FAR*LPPREFIX;typedef struct tagPOSTFIX FAR*LPPOSTFIX;/*--- Prefix structure before every heap object---*/typedef struct tagPREFIX { LPPREFIX lpPrev; /* previous object in heap */ LPPREFIX lpNext; /* next object in heap */ LPPOSTFIX lpPostfix; /* ptr to postfix object */ LPSTR lpFilename; /* filename ptr or NULL */ long lLineNumber; /* line number or 0 */ LPVOID lpMem; /* FmNew() ptr of object */ LPCLASSDESC lpClassDesc; /* class descriptor ptr or NULL */ } PREFIX;/*--- Postfix structure after every heap object ---*/typedef struct tagPOSTFIX { LPPREFIX lpPrefix; } POSTFIX;/*--- Verify alignment of prefix structure ---*/CompilerAssert(!(sizeof(PREFIX)%ALIGNMENT));/*--- Points to first object in linked list of heap objects ---*/static LPPREFIX lpHeapHead=NULL;/*--- Local prototypes ---*/void LOCAL AddToLinkedList ( LPPREFIX );void LOCAL RemoveFromLinkedList ( LPPREFIX );BOOL LOCAL VerifyHeapPointer ( LPVOID );void LOCAL RenderDesc ( LPPREFIX, LPSTR );/*pf-------------------------------------------------------------- * * DESCRIPTION: (Far Memory New) JLJ * * Allocate a new block of memory from the heap. * * ARGUMENTS: * * wSize - Size of object to allocate * lpClassDesc - Class descriptor for object (or NULL) * lpFile - Filename where object was allocated * nLine - Line number where object was allocated * * RETURNS: * * A long pointer to the memory object or NULL * *--------------------------------------------------------------*/LPVOID APIENTRY FmNew( SIZET wSize, LPCLASSDESC lpClassDesc, LPSTR lpFile, int nLine ){ LPPREFIX lpPrefix; wSize = DOALIGN(wSize); lpPrefix=(LPPREFIX)malloc(sizeof(PREFIX)+wSize+sizeof(POSTFIX)); if (lpPrefix) { AddToLinkedList( lpPrefix ); lpPrefix->lpPostfix = (LPPOSTFIX)((LPSTR)(lpPrefix+1)+wSize); lpPrefix->lpPostfix->lpPrefix = lpPrefix; lpPrefix->lpFilename = lpFile; lpPrefix->lLineNumber = nLine; lpPrefix->lpMem = lpPrefix+1; lpPrefix->lpClassDesc = lpClassDesc; memset( lpPrefix->lpMem, 0, wSize );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -