Ignore:
Timestamp:
Nov 23, 2000, 7:36:41 PM (25 years ago)
Author:
umoeller
Message:

Updates for V0.9.6.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/memdebug.c

    r8 r13  
    11
    22/*
    3  * memdebug.c:
    4  *      memory debugging helpers. Memory debugging is enabled
    5  *      if the __XWPMEMDEBUG__ #define is set in setup.h.
     3 *@@sourcefile memdebug.c:
     4 *      memory debugging helpers.
    65 *
    76 *      Several things are in here which might turn out to
     
    1211 *      -- Sophisticated heap debugging functions, which
    1312 *         automatically replace malloc() and free() etc.
    14  *         when XWorkplace is compiled with debug code.
     13 *         If the __XWPMEMDEBUG__ #define is set before including
     14 *         memdebug.h, all those standard library calls
     15 *         are remapped to use the functions in this file
     16 *         instead.
     17 *
     18 *         At present, malloc(), calloc(), realloc(), strdup()
     19 *         and free() are supported.
     20 *
    1521 *         These log every memory allocation made and log
    1622 *         much more data compared to the VAC++ memory
     
    2834 *         function.
    2935 *
    30  *         At present, malloc(), calloc(), strdup() and free()
    31  *         are supported. If you invoke free() on a memory block
    32  *         allocated by a function other than the above, you'll
    33  *         get a runtime error.
    34  *
    3536 *         These debug functions have been added with V0.9.3
    3637 *         and should now be compiler-independent.
    3738 *
    38  *      -- A PM heap debugging window which shows the statuzs
     39 *         V0.9.6 added realloc() support and fixed a few bugs.
     40 *
     41 *      -- A PM heap debugging window which shows the status
    3942 *         of the heap logging list. See memdCreateMemDebugWindow
    40  *         for details.
    41  *
    42  *      To enable memory debugging, do the following:
     43 *         (memdebug_win.c) for details.
     44 *
     45 *      To enable memory debugging, do the following in each (!)
     46 *      of your code modules:
    4347 *
    4448 *      1) Include at least <stdlib.h> and <string.h>.
     
    5357 *      That's all. XWorkplace's setup.h does this automatically
    5458 *      if XWorkplace is compiled with debug code.
     59 *
     60 *      A couple of WARNINGS:
     61 *
     62 *      1)  Memory debugging can greatly slow down the system
     63 *          after a while. When free() is invoked, the memory
     64 *          that was allocated is freed, but not the memory
     65 *          log entry (the HEAPITEM) to allow tracing what was
     66 *          freed. As a result, the linked list of memory items
     67 *          keeps growing longer, and free() becomes terribly
     68 *          slow after a while because it must traverse the
     69 *          entire list for each free() call. Use memdReleaseFreed
     70 *          from time to time.
     71 *
     72 *      2)  The replacement functions in this file allocate
     73 *          extra memory for the magic strings. For example, if
     74 *          you call malloc(100), more than 100 bytes get allocated
     75 *          to allow for storing the magic strings to detect
     76 *          memory overwrites. Two magic strings are allocated,
     77 *          one before the actual buffer, and one behind it.
     78 *
     79 *          As a result, YOU MUST NOT confuse the replacement
     80 *          memory functions with the original ones. If you
     81 *          use malloc() in one source file and free() the
     82 *          buffer in another one where debug memory has not
     83 *          been enabled, you'll get crashes.
     84 *
     85 *          As a rule of thumb, enable memory debugging for all
     86 *          your source files or for none. And make sure everything
     87 *          is recompiled when you change your mind.
    5588 *
    5689 *@@added V0.9.1 (2000-02-12) [umoeller]
     
    80113#define INCL_DOSERRORS
    81114
    82 #define INCL_WINWINDOWMGR
    83 #define INCL_WINFRAMEMGR
    84 #define INCL_WINCOUNTRY
    85 #define INCL_WINSYS
    86 #define INCL_WINMENUS
    87 #define INCL_WINSTDCNR
    88115#include <os2.h>
    89116
    90117#include <stdio.h>
    91118#include <string.h>
    92 // #include <malloc.h>
    93119#include <setjmp.h>
    94120
    95 #define DONT_REPLACE_MALLOC             // we need the "real" malloc in this file
     121#define DONT_REPLACE_MALLOC             // never do debug memory for this
     122#define MEMDEBUG_PRIVATE
    96123#include "setup.h"
    97124
    98125#ifdef __XWPMEMDEBUG__
    99126
    100 #include "helpers\cnrh.h"
    101127#include "helpers\except.h"
    102 // #include "helpers\memdebug.h"        // included by setup.h already
     128#include "helpers\memdebug.h"        // included by setup.h already
    103129#include "helpers\stringh.h"
    104 #include "helpers\winh.h"
    105130
    106131/*
     
    120145#define MEMBLOCKMAGIC_TAIL     "\250\210&%/dfjsk%#,dlhf\223"
    121146
    122 /*
    123  *@@ HEAPITEM:
    124  *      informational structure created for each
    125  *      malloc() call by memdMalloc. These are stored
    126  *      in a global linked list (G_pHeapItemsRoot).
    127  *
    128  *      We cannot use the linklist.c functions for
    129  *      managing the linked list because these use
    130  *      malloc in turn, which would lead to infinite
    131  *      loops.
    132  *
    133  *@@added V0.9.3 (2000-04-11) [umoeller]
    134  */
    135 
    136 typedef struct _HEAPITEM
    137 {
    138     struct _HEAPITEM    *pNext;     // next item in linked list or NULL if last
    139 
    140     void                *pAfterMagic; // memory pointer returned by memdMalloc;
    141                                     // this points to after the magic string
    142     unsigned long       ulSize;     // size of *pData
    143 
    144     const char          *pcszSourceFile;    // as passed to memdMalloc
    145     unsigned long       ulLine;             // as passed to memdMalloc
    146     const char          *pcszFunction;      // as passed to memdMalloc
    147 
    148     DATETIME            dtAllocated;        // system date/time at time of memdMalloc call
    149 
    150     ULONG               ulTID;      // thread ID that memdMalloc was running on
    151 
    152     BOOL                fFreed;     // TRUE only after item has been freed by memdFree
    153 } HEAPITEM, *PHEAPITEM;
    154 
    155147HMTX            G_hmtxMallocList = NULLHANDLE;
    156148
    157 PHEAPITEM       G_pHeapItemsRoot = NULL,
    158                 G_pHeapItemsLast = NULL;
    159 
    160 PSZ             G_pszMemCnrTitle = NULL;
     149extern PHEAPITEM G_pHeapItemsRoot = NULL;
     150PHEAPITEM       G_pHeapItemsLast = NULL;
    161151
    162152PFNCBMEMDLOG    G_pMemdLogFunc = NULL;
    163153
    164 ULONG           G_ulItemsReleased = 0,
    165                 G_ulBytesReleased = 0;
     154extern ULONG    G_ulItemsReleased = 0;
     155extern ULONG    G_ulBytesReleased = 0;
    166156
    167157/* ******************************************************************
     
    189179        arc = DosCreateMutexSem(NULL,
    190180                                &G_hmtxMallocList,
    191                                 0,
    192                                 FALSE);
    193 
    194     arc = DosRequestMutexSem(G_hmtxMallocList,
    195                              SEM_INDEFINITE_WAIT);
     181                                0,          // unshared
     182                                TRUE);      // request now!
     183    else
     184        arc = DosRequestMutexSem(G_hmtxMallocList,
     185                                 SEM_INDEFINITE_WAIT);
    196186
    197187    return (arc == NO_ERROR);
     
    435425                    pHeapItem->fFreed = TRUE;
    436426
    437                     /* lstRemoveNode(&G_llHeapItems,
    438                                   pNode); */
    439427                    fFound = TRUE;
    440428                    break;
    441                 }
     429                } // if (!pHeapItem->fFreed)
    442430
    443431            pHeapItem = pHeapItem->pNext;
     
    452440            CHAR szMsg[1000];
    453441            sprintf(szMsg,
    454                     "free() failed. Called from %s (%s, line %d) for object 0x%lX.",
     442                    "free() called with invalid object from %s (%s, line %d) for object 0x%lX.",
    455443                    pcszFunction,
    456444                        pcszSourceFile,
     
    459447            G_pMemdLogFunc(szMsg);
    460448        }
     449}
     450
     451/*
     452 *@@ memdRealloc:
     453 *      wrapper function for realloc(). See memdMalloc for
     454 *      details.
     455 *
     456 *@@added V0.9.6 (2000-11-12) [umoeller]
     457 */
     458
     459void* memdRealloc(void *p,
     460                  size_t stSize,
     461                  const char *pcszSourceFile, // in: source file name
     462                  unsigned long ulLine,       // in: source line
     463                  const char *pcszFunction)   // in: function name
     464{
     465    void *prc = NULL;
     466    BOOL fFound = FALSE;
     467
     468    if (memdLock())
     469    {
     470        PHEAPITEM pHeapItem = G_pHeapItemsRoot;
     471
     472        // search the list with the pointer which was
     473        // really returned by the original malloc(),
     474        // that is, the byte before the magic string
     475        void *pBeforeMagic = ((PBYTE)p) - sizeof(MEMBLOCKMAGIC_HEAD);
     476
     477        while (pHeapItem)
     478        {
     479            if (pHeapItem->pAfterMagic == p)
     480                // the same address may be allocated and freed
     481                // several times, so if this address has been
     482                // freed, search on
     483                if (!pHeapItem->fFreed)
     484                {
     485                    // found:
     486                    PVOID   pObjNew = 0;
     487                    ULONG   ulError = 0;
     488                    ULONG   cbCopy = 0;
     489                    PTIB    ptib;
     490                    PPIB    ppib;
     491
     492                    // check magic string
     493                    if (memcmp(pBeforeMagic,
     494                               MEMBLOCKMAGIC_HEAD,
     495                               sizeof(MEMBLOCKMAGIC_HEAD))
     496                            != 0)
     497                        ulError = 1;
     498                    else if (memcmp(((PBYTE)pHeapItem->pAfterMagic) + pHeapItem->ulSize,
     499                                    MEMBLOCKMAGIC_TAIL,
     500                                    sizeof(MEMBLOCKMAGIC_TAIL))
     501                            != 0)
     502                        ulError = 2;
     503
     504                    if (ulError)
     505                    {
     506                        // magic block has been overwritten:
     507                        if (G_pMemdLogFunc)
     508                        {
     509                            CHAR szMsg[1000];
     510                            sprintf(szMsg,
     511                                    "Magic string %s memory block at 0x%lX has been overwritten.\n"
     512                                    "This was detected by the realloc() call at %s (%s, line %d).\n"
     513                                    "The block was allocated by %s (%s, line %d).",
     514                                    (ulError == 1) ? "before" : "after",
     515                                    p,
     516                                    pcszFunction,
     517                                        pcszSourceFile,
     518                                        ulLine, // free
     519                                    pHeapItem->pcszFunction,
     520                                        pHeapItem->pcszSourceFile,
     521                                        pHeapItem->ulLine);
     522                            G_pMemdLogFunc(szMsg);
     523                        }
     524                    }
     525
     526                    // now reallocate!
     527                    pObjNew = malloc(stSize   // new size
     528                                     + sizeof(MEMBLOCKMAGIC_HEAD)
     529                                     + sizeof(MEMBLOCKMAGIC_TAIL));
     530
     531                    // store "front" magic string
     532                    memcpy(pObjNew,
     533                           MEMBLOCKMAGIC_HEAD,
     534                           sizeof(MEMBLOCKMAGIC_HEAD));
     535                    // return address: first byte after "front" magic string
     536                    prc = ((PBYTE)pObjNew) + sizeof(MEMBLOCKMAGIC_HEAD);
     537
     538                    // bytes to copy: the smaller of the old and the new size
     539                    cbCopy = pHeapItem->ulSize;
     540                    if (stSize < pHeapItem->ulSize)
     541                        cbCopy = stSize;
     542
     543                    // copy buffer from old memory object
     544                    memcpy(prc,         // after "front" magic
     545                           pHeapItem->pAfterMagic,
     546                           cbCopy);
     547
     548                    // store "tail" magic string to block which
     549                    // will be returned plus the size which was requested
     550                    memcpy(((PBYTE)prc) + stSize,
     551                           MEMBLOCKMAGIC_TAIL,
     552                           sizeof(MEMBLOCKMAGIC_TAIL));
     553
     554                    // free the old buffer
     555                    free(pBeforeMagic);
     556
     557                    // update the HEAPITEM
     558                    pHeapItem->pAfterMagic = prc;       // new pointer!
     559                    pHeapItem->ulSize = stSize;         // new size!
     560                    pHeapItem->pcszSourceFile = pcszSourceFile;
     561                    pHeapItem->ulLine = ulLine;
     562                    pHeapItem->pcszFunction = pcszFunction;
     563
     564                    // update date, time, TID
     565                    DosGetDateTime(&pHeapItem->dtAllocated);
     566                    pHeapItem->ulTID = 0;
     567                    if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR)
     568                        if (ptib)
     569                            if (ptib->tib_ptib2)
     570                                pHeapItem->ulTID = ptib->tib_ptib2->tib2_ultid;
     571
     572                    fFound = TRUE;
     573                    break;
     574                } // if (!pHeapItem->fFreed)
     575
     576            pHeapItem = pHeapItem->pNext;
     577        }
     578
     579        memdUnlock();
     580    }
     581
     582    if (!fFound)
     583        if (G_pMemdLogFunc)
     584        {
     585            CHAR szMsg[1000];
     586            sprintf(szMsg,
     587                    "realloc() called with invalid object from %s (%s, line %d) for object 0x%lX.",
     588                    pcszFunction,
     589                        pcszSourceFile,
     590                        ulLine,
     591                    p);
     592            G_pMemdLogFunc(szMsg);
     593        }
     594
     595    return (prc);
    461596}
    462597
     
    485620        while (pHeapItem)
    486621        {
     622            // store next first, because we can change the "next" pointer
    487623            PHEAPITEM   pNext = pHeapItem->pNext;       // can be NULL
     624
    488625            if (pHeapItem->fFreed)
    489626            {
    490                 // item freed:
     627                // item was freed:
    491628                if (pPrevious == NULL)
    492629                    // head of list:
     
    499636                ulItemsReleased++;
    500637                ulBytesReleased += pHeapItem->ulSize;
     638
     639                if (pHeapItem == G_pHeapItemsLast)
     640                    // reset "last item" cache
     641                    G_pHeapItemsLast = NULL;
    501642
    502643                free(pHeapItem);
     
    550691#endif
    551692
    552 /* ******************************************************************
    553  *                                                                  *
    554  *   Heap debugging window                                          *
    555  *                                                                  *
    556  ********************************************************************/
    557 
    558 /*
    559  *@@ MEMRECORD:
    560  *
    561  *@@added V0.9.1 (99-12-04) [umoeller]
    562  */
    563 
    564 typedef struct _MEMRECORD
    565 {
    566     RECORDCORE  recc;
    567 
    568     ULONG       ulIndex;
    569 
    570     CDATE       cdateAllocated;
    571     CTIME       ctimeAllocated;
    572 
    573     PSZ         pszFreed;
    574 
    575     ULONG       ulTID;
    576 
    577     PSZ         pszFunction;    // points to szFunction
    578     CHAR        szFunction[400];
    579 
    580     PSZ         pszSource;      // points to szSource
    581     CHAR        szSource[CCHMAXPATH];
    582 
    583     ULONG       ulLine;
    584 
    585     PSZ         pszAddress;     // points to szAddress
    586     CHAR        szAddress[20];
    587 
    588     ULONG       ulSize;
    589 
    590 } MEMRECORD, *PMEMRECORD;
    591 
    592 /* ULONG       ulHeapItemsCount1,
    593             ulHeapItemsCount2;
    594 ULONG       ulTotalAllocated,
    595             ulTotalFreed;
    596 PMEMRECORD  pMemRecordThis = NULL;
    597 PSZ         pszMemCnrTitle = NULL; */
    598 
    599 #if 0
    600     /*
    601      *@@ fncbMemHeapWalkCount:
    602      *      callback func for _heap_walk function used for
    603      *      fnwpMemDebug.
    604      *
    605      *@@added V0.9.1 (99-12-04) [umoeller]
    606      */
    607 
    608     int fncbMemHeapWalkCount(const void *pObject,
    609                              size_t Size,
    610                              int useflag,
    611                              int status,
    612                              const char *filename,
    613                              size_t line)
    614     {
    615         // skip all the items which seem to be
    616         // internal to the runtime
    617         if ((filename) || (useflag == _FREEENTRY))
    618         {
    619             ulHeapItemsCount1++;
    620             if (useflag == _FREEENTRY)
    621                 ulTotalFreed += Size;
    622             else
    623                 ulTotalAllocated += Size;
    624         }
    625         return (0);
    626     }
    627 
    628     /*
    629      *@@ fncbMemHeapWalkFill:
    630      *      callback func for _heap_walk function used for
    631      *      fnwpMemDebug.
    632      *
    633      *@@added V0.9.1 (99-12-04) [umoeller]
    634      */
    635 
    636     int fncbMemHeapWalkFill(const void *pObject,
    637                             size_t Size,
    638                             int useflag,
    639                             int status,
    640                             const char *filename,
    641                             size_t line)
    642     {
    643         // skip all the items which seem to be
    644         // internal to the runtime
    645         if ((filename) || (useflag == _FREEENTRY))
    646         {
    647             ulHeapItemsCount2++;
    648             if ((pMemRecordThis) && (ulHeapItemsCount2 < ulHeapItemsCount1))
    649             {
    650                 pMemRecordThis->ulIndex = ulHeapItemsCount2 - 1;
    651 
    652                 pMemRecordThis->pObject = pObject;
    653                 pMemRecordThis->useflag = useflag;
    654                 pMemRecordThis->status = status;
    655                 pMemRecordThis->filename = filename;
    656 
    657                 pMemRecordThis->pszAddress = pMemRecordThis->szAddress;
    658 
    659                 pMemRecordThis->ulSize = Size;
    660 
    661                 pMemRecordThis->pszSource = pMemRecordThis->szSource;
    662 
    663                 pMemRecordThis->ulLine = line;
    664 
    665                 pMemRecordThis = (PMEMRECORD)pMemRecordThis->recc.preccNextRecord;
    666             }
    667             else
    668                 return (1);     // stop
    669         }
    670 
    671         return (0);
    672     }
    673 
    674     /*
    675      *@@ memdCreateRecordsVAC:
    676      *
    677      *@@added V0.9.3 (2000-04-10) [umoeller]
    678      */
    679 
    680     VOID memdCreateRecordsVAC(HWND hwndCnr)
    681     {
    682         // count heap items
    683         ulHeapItemsCount1 = 0;
    684         ulTotalFreed = 0;
    685         ulTotalAllocated = 0;
    686         _heap_walk(fncbMemHeapWalkCount);
    687 
    688         pMemRecordFirst = (PMEMRECORD)cnrhAllocRecords(hwndCnr,
    689                                                        sizeof(MEMRECORD),
    690                                                        ulHeapItemsCount1);
    691         if (pMemRecordFirst)
    692         {
    693             ulHeapItemsCount2 = 0;
    694             pMemRecordThis = pMemRecordFirst;
    695             _heap_walk(fncbMemHeapWalkFill);
    696 
    697             // the following doesn't work while _heap_walk is running
    698             pMemRecordThis = pMemRecordFirst;
    699             while (pMemRecordThis)
    700             {
    701                 switch (pMemRecordThis->useflag)
    702                 {
    703                     case _USEDENTRY: pMemRecordThis->pszUseFlag = "Used"; break;
    704                     case _FREEENTRY: pMemRecordThis->pszUseFlag = "Freed"; break;
    705                 }
    706 
    707                 switch (pMemRecordThis->status)
    708                 {
    709                     case _HEAPBADBEGIN: pMemRecordThis->pszStatus = "heap bad begin"; break;
    710                     case _HEAPBADNODE: pMemRecordThis->pszStatus = "heap bad node"; break;
    711                     case _HEAPEMPTY: pMemRecordThis->pszStatus = "heap empty"; break;
    712                     case _HEAPOK: pMemRecordThis->pszStatus = "OK"; break;
    713                 }
    714 
    715                 sprintf(pMemRecordThis->szAddress, "0x%lX", pMemRecordThis->pObject);
    716                 strcpy(pMemRecordThis->szSource,
    717                         (pMemRecordThis->filename)
    718                             ? pMemRecordThis->filename
    719                             : "?");
    720 
    721                 pMemRecordThis = (PMEMRECORD)pMemRecordThis->recc.preccNextRecord;
    722             }
    723 
    724             cnrhInsertRecords(hwndCnr,
    725                               NULL,         // parent
    726                               (PRECORDCORE)pMemRecordFirst,
    727                               TRUE,
    728                               NULL,
    729                               CRA_RECORDREADONLY,
    730                               ulHeapItemsCount2);
    731         }
    732     }
    733 
    734 #endif
    735 
    736 /*
    737  *@@ memdCreateRecords:
    738  *
    739  *@@added V0.9.3 (2000-04-10) [umoeller]
    740  */
    741 
    742 VOID memdCreateRecords(HWND hwndCnr,
    743                        PULONG pulTotalItems,
    744                        PULONG pulAllocatedItems,
    745                        PULONG pulFreedItems,
    746                        PULONG pulTotalBytes,
    747                        PULONG pulAllocatedBytes,
    748                        PULONG pulFreedBytes)
    749 {
    750     // count heap items
    751     ULONG       ulHeapItemsCount1 = 0;
    752     PMEMRECORD  pMemRecordFirst;
    753 
    754     if (memdLock())
    755     {
    756         // PLISTNODE   pNode = lstQueryFirstNode(&G_llHeapItems);
    757         PHEAPITEM pHeapItem = G_pHeapItemsRoot;
    758 
    759         *pulTotalItems = 0;
    760         *pulAllocatedItems = 0;
    761         *pulFreedItems = 0;
    762 
    763         *pulTotalBytes = 0;
    764         *pulAllocatedBytes = 0;
    765         *pulFreedBytes = 0;
    766 
    767         while (pHeapItem)
    768         {
    769             ulHeapItemsCount1++;
    770             if (pHeapItem->fFreed)
    771             {
    772                 (*pulFreedItems)++;
    773                 (*pulFreedBytes) += pHeapItem->ulSize;
    774             }
    775             else
    776             {
    777                 (*pulAllocatedItems)++;
    778                 (*pulAllocatedBytes) += pHeapItem->ulSize;
    779             }
    780 
    781             (*pulTotalBytes) += pHeapItem->ulSize;
    782 
    783             pHeapItem = pHeapItem->pNext;
    784         }
    785 
    786         *pulTotalItems = ulHeapItemsCount1;
    787 
    788         pMemRecordFirst = (PMEMRECORD)cnrhAllocRecords(hwndCnr,
    789                                                        sizeof(MEMRECORD),
    790                                                        ulHeapItemsCount1);
    791         if (pMemRecordFirst)
    792         {
    793             ULONG       ulHeapItemsCount2 = 0;
    794             PMEMRECORD  pMemRecordThis = pMemRecordFirst;
    795             pHeapItem = G_pHeapItemsRoot;
    796             // PLISTNODE   pMemNode = lstQueryFirstNode(&G_llHeapItems);
    797 
    798             while ((pMemRecordThis) && (pHeapItem))
    799             {
    800                 // PHEAPITEM pHeapItem = (PHEAPITEM)pMemNode->pItemData;
    801 
    802                 pMemRecordThis->ulIndex = ulHeapItemsCount2++;
    803 
    804                 cnrhDateTimeDos2Win(&pHeapItem->dtAllocated,
    805                                     &pMemRecordThis->cdateAllocated,
    806                                     &pMemRecordThis->ctimeAllocated);
    807 
    808                 if (pHeapItem->fFreed)
    809                     pMemRecordThis->pszFreed = "yes";
    810 
    811                 pMemRecordThis->ulTID = pHeapItem->ulTID;
    812 
    813                 strcpy(pMemRecordThis->szSource, pHeapItem->pcszSourceFile);
    814                 pMemRecordThis->pszSource = pMemRecordThis->szSource;
    815 
    816                 pMemRecordThis->ulLine = pHeapItem->ulLine;
    817 
    818                 strcpy(pMemRecordThis->szFunction, pHeapItem->pcszFunction);
    819                 pMemRecordThis->pszFunction = pMemRecordThis->szFunction;
    820 
    821                 sprintf(pMemRecordThis->szAddress, "0x%lX", pHeapItem->pAfterMagic);
    822                 pMemRecordThis->pszAddress = pMemRecordThis->szAddress;
    823 
    824                 pMemRecordThis->ulSize = pHeapItem->ulSize;
    825 
    826 
    827                 /* switch (pMemRecordThis->useflag)
    828                 {
    829                     case _USEDENTRY: pMemRecordThis->pszUseFlag = "Used"; break;
    830                     case _FREEENTRY: pMemRecordThis->pszUseFlag = "Freed"; break;
    831                 }
    832 
    833                 switch (pMemRecordThis->status)
    834                 {
    835                     case _HEAPBADBEGIN: pMemRecordThis->pszStatus = "heap bad begin"; break;
    836                     case _HEAPBADNODE: pMemRecordThis->pszStatus = "heap bad node"; break;
    837                     case _HEAPEMPTY: pMemRecordThis->pszStatus = "heap empty"; break;
    838                     case _HEAPOK: pMemRecordThis->pszStatus = "OK"; break;
    839                 }
    840 
    841                 sprintf(pMemRecordThis->szAddress, "0x%lX", pMemRecordThis->pObject);
    842                 strcpy(pMemRecordThis->szSource,
    843                         (pMemRecordThis->filename)
    844                             ? pMemRecordThis->filename
    845                             : "?"); */
    846 
    847                 pMemRecordThis = (PMEMRECORD)pMemRecordThis->recc.preccNextRecord;
    848                 pHeapItem = pHeapItem->pNext;
    849             }
    850 
    851             cnrhInsertRecords(hwndCnr,
    852                               NULL,         // parent
    853                               (PRECORDCORE)pMemRecordFirst,
    854                               TRUE,
    855                               NULL,
    856                               CRA_RECORDREADONLY,
    857                               ulHeapItemsCount2);
    858         }
    859 
    860         memdUnlock();
    861     }
    862 }
    863 
    864 /*
    865  *@@ mnu_fnCompareIndex:
    866  *
    867  *@@added V0.9.1 (99-12-03) [umoeller]
    868  */
    869 
    870 SHORT EXPENTRY mnu_fnCompareIndex(PMEMRECORD pmrc1, PMEMRECORD  pmrc2, PVOID pStorage)
    871 {
    872     // HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
    873     pStorage = pStorage; // to keep the compiler happy
    874     if ((pmrc1) && (pmrc2))
    875         if (pmrc1->ulIndex < pmrc2->ulIndex)
    876             return (-1);
    877         else if (pmrc1->ulIndex > pmrc2->ulIndex)
    878             return (1);
    879 
    880     return (0);
    881 }
    882 
    883 /*
    884  *@@ mnu_fnCompareSourceFile:
    885  *
    886  *@@added V0.9.1 (99-12-03) [umoeller]
    887  */
    888 
    889 SHORT EXPENTRY mnu_fnCompareSourceFile(PMEMRECORD pmrc1, PMEMRECORD  pmrc2, PVOID pStorage)
    890 {
    891     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
    892     pStorage = pStorage; // to keep the compiler happy
    893     if ((pmrc1) && (pmrc2))
    894             switch (WinCompareStrings(habDesktop, 0, 0,
    895                                       pmrc1->szSource,
    896                                       pmrc2->szSource,
    897                                       0))
    898             {
    899                 case WCS_LT: return (-1);
    900                 case WCS_GT: return (1);
    901                 default:    // equal
    902                     if (pmrc1->ulLine < pmrc2->ulLine)
    903                         return (-1);
    904                     else if (pmrc1->ulLine > pmrc2->ulLine)
    905                         return (1);
    906 
    907             }
    908 
    909     return (0);
    910 }
    911 
    912 #define ID_MEMCNR   1000
    913 
    914 /*
    915  *@@ memd_fnwpMemDebug:
    916  *      client window proc for the heap debugger window
    917  *      accessible from the Desktop context menu if
    918  *      __XWPMEMDEBUG__ is defined. Otherwise, this is not
    919  *      compiled.
    920  *
    921  *      Usage: this is a regular PM client window procedure
    922  *      to be used with WinRegisterClass and WinCreateStdWindow.
    923  *      See dtpMenuItemSelected, which uses this.
    924  *
    925  *      This creates a container with all the memory objects
    926  *      with the size of the client area in turn.
    927  *
    928  *@@added V0.9.1 (99-12-04) [umoeller]
    929  */
    930 
    931 
    932 MRESULT EXPENTRY memd_fnwpMemDebug(HWND hwndClient, ULONG msg, MPARAM mp1, MPARAM mp2)
    933 {
    934     MRESULT mrc = 0;
    935 
    936     switch (msg)
    937     {
    938         case WM_CREATE:
    939         {
    940             TRY_LOUD(excpt1, NULL)
    941             {
    942                 // PCREATESTRUCT pcs = (PCREATESTRUCT)mp2;
    943                 HWND hwndCnr;
    944                 hwndCnr = WinCreateWindow(hwndClient,        // parent
    945                                           WC_CONTAINER,
    946                                           "",
    947                                           WS_VISIBLE | CCS_MINIICONS | CCS_READONLY | CCS_SINGLESEL,
    948                                           0, 0, 0, 0,
    949                                           hwndClient,        // owner
    950                                           HWND_TOP,
    951                                           ID_MEMCNR,
    952                                           NULL, NULL);
    953                 if (hwndCnr)
    954                 {
    955                     XFIELDINFO      xfi[11];
    956                     PFIELDINFO      pfi = NULL;
    957                     PMEMRECORD      pMemRecordFirst;
    958                     int             i = 0;
    959 
    960                     ULONG           ulTotalItems = 0,
    961                                     ulAllocatedItems = 0,
    962                                     ulFreedItems = 0;
    963                     ULONG           ulTotalBytes = 0,
    964                                     ulAllocatedBytes = 0,
    965                                     ulFreedBytes = 0;
    966 
    967                     // set up cnr details view
    968                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulIndex);
    969                     xfi[i].pszColumnTitle = "No.";
    970                     xfi[i].ulDataType = CFA_ULONG;
    971                     xfi[i++].ulOrientation = CFA_RIGHT;
    972 
    973                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, cdateAllocated);
    974                     xfi[i].pszColumnTitle = "Date";
    975                     xfi[i].ulDataType = CFA_DATE;
    976                     xfi[i++].ulOrientation = CFA_LEFT;
    977 
    978                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ctimeAllocated);
    979                     xfi[i].pszColumnTitle = "Time";
    980                     xfi[i].ulDataType = CFA_TIME;
    981                     xfi[i++].ulOrientation = CFA_LEFT;
    982 
    983                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszFreed);
    984                     xfi[i].pszColumnTitle = "Freed";
    985                     xfi[i].ulDataType = CFA_STRING;
    986                     xfi[i++].ulOrientation = CFA_CENTER;
    987 
    988                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulTID);
    989                     xfi[i].pszColumnTitle = "TID";
    990                     xfi[i].ulDataType = CFA_ULONG;
    991                     xfi[i++].ulOrientation = CFA_RIGHT;
    992 
    993                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszFunction);
    994                     xfi[i].pszColumnTitle = "Function";
    995                     xfi[i].ulDataType = CFA_STRING;
    996                     xfi[i++].ulOrientation = CFA_LEFT;
    997 
    998                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszSource);
    999                     xfi[i].pszColumnTitle = "Source";
    1000                     xfi[i].ulDataType = CFA_STRING;
    1001                     xfi[i++].ulOrientation = CFA_LEFT;
    1002 
    1003                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulLine);
    1004                     xfi[i].pszColumnTitle = "Line";
    1005                     xfi[i].ulDataType = CFA_ULONG;
    1006                     xfi[i++].ulOrientation = CFA_RIGHT;
    1007 
    1008                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulSize);
    1009                     xfi[i].pszColumnTitle = "Size";
    1010                     xfi[i].ulDataType = CFA_ULONG;
    1011                     xfi[i++].ulOrientation = CFA_RIGHT;
    1012 
    1013                     xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszAddress);
    1014                     xfi[i].pszColumnTitle = "Address";
    1015                     xfi[i].ulDataType = CFA_STRING;
    1016                     xfi[i++].ulOrientation = CFA_LEFT;
    1017 
    1018                     pfi = cnrhSetFieldInfos(hwndCnr,
    1019                                             &xfi[0],
    1020                                             i,             // array item count
    1021                                             TRUE,          // no draw lines
    1022                                             3);            // return column
    1023 
    1024                     {
    1025                         PSZ pszFont = "9.WarpSans";
    1026                         WinSetPresParam(hwndCnr,
    1027                                         PP_FONTNAMESIZE,
    1028                                         strlen(pszFont),
    1029                                         pszFont);
    1030                     }
    1031 
    1032                     memdCreateRecords(hwndCnr,
    1033                                       &ulTotalItems,
    1034                                       &ulAllocatedItems,
    1035                                       &ulFreedItems,
    1036                                       &ulTotalBytes,
    1037                                       &ulAllocatedBytes,
    1038                                       &ulFreedBytes);
    1039 
    1040                     BEGIN_CNRINFO()
    1041                     {
    1042                         CHAR    szCnrTitle[1000];
    1043                         CHAR    szTotalItems[100],
    1044                                 szAllocatedItems[100],
    1045                                 szFreedItems[100],
    1046                                 szReleasedItems[100];
    1047                         CHAR    szTotalBytes[100],
    1048                                 szAllocatedBytes[100],
    1049                                 szFreedBytes[100],
    1050                                 szReleasedBytes[100];
    1051                         sprintf(szCnrTitle,
    1052                                 "Total logs in use: %s items = %s bytes\n"
    1053                                 "    Total in use: %s items = %s bytes\n"
    1054                                 "    Total freed: %s items = %s bytes\n"
    1055                                 "Total logs released: %s items = %s bytes",
    1056                                 strhThousandsDouble(szTotalItems,
    1057                                                     ulTotalItems,
    1058                                                     '.'),
    1059                                 strhThousandsDouble(szTotalBytes,
    1060                                                     ulTotalBytes,
    1061                                                     '.'),
    1062                                 strhThousandsDouble(szAllocatedItems,
    1063                                                     ulAllocatedItems,
    1064                                                     '.'),
    1065                                 strhThousandsDouble(szAllocatedBytes,
    1066                                                     ulAllocatedBytes,
    1067                                                     '.'),
    1068                                 strhThousandsDouble(szFreedItems,
    1069                                                     ulFreedItems,
    1070                                                     '.'),
    1071                                 strhThousandsDouble(szFreedBytes,
    1072                                                     ulFreedBytes,
    1073                                                     '.'),
    1074                                 strhThousandsDouble(szReleasedItems,
    1075                                                     G_ulItemsReleased,
    1076                                                     '.'),
    1077                                 strhThousandsDouble(szReleasedBytes,
    1078                                                     G_ulBytesReleased,
    1079                                                     '.'));
    1080                         G_pszMemCnrTitle = strdup(szCnrTitle);
    1081                         cnrhSetTitle(G_pszMemCnrTitle);
    1082                         cnrhSetView(CV_DETAIL | CV_MINI | CA_DETAILSVIEWTITLES
    1083                                         | CA_DRAWICON
    1084                                     | CA_CONTAINERTITLE | CA_TITLEREADONLY
    1085                                         | CA_TITLESEPARATOR | CA_TITLELEFT);
    1086                         cnrhSetSplitBarAfter(pfi);
    1087                         cnrhSetSplitBarPos(250);
    1088                     } END_CNRINFO(hwndCnr);
    1089 
    1090                     WinSetFocus(HWND_DESKTOP, hwndCnr);
    1091                 }
    1092             }
    1093             CATCH(excpt1) {} END_CATCH();
    1094 
    1095             mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
    1096         break; }
    1097 
    1098         case WM_WINDOWPOSCHANGED:
    1099         {
    1100             PSWP pswp = (PSWP)mp1;
    1101             mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
    1102             if (pswp->fl & SWP_SIZE)
    1103             {
    1104                 WinSetWindowPos(WinWindowFromID(hwndClient, ID_MEMCNR), // cnr
    1105                                 HWND_TOP,
    1106                                 0, 0, pswp->cx, pswp->cy,
    1107                                 SWP_SIZE | SWP_MOVE | SWP_SHOW);
    1108             }
    1109         break; }
    1110 
    1111         case WM_CONTROL:
    1112         {
    1113             USHORT usItemID = SHORT1FROMMP(mp1),
    1114                    usNotifyCode = SHORT2FROMMP(mp1);
    1115             if (usItemID == ID_MEMCNR)       // cnr
    1116             {
    1117                 switch (usNotifyCode)
    1118                 {
    1119                     case CN_CONTEXTMENU:
    1120                     {
    1121                         PMEMRECORD precc = (PMEMRECORD)mp2;
    1122                         if (precc == NULL)
    1123                         {
    1124                             // whitespace
    1125                             HWND hwndMenu = WinCreateMenu(HWND_DESKTOP,
    1126                                                           NULL); // no menu template
    1127                             winhInsertMenuItem(hwndMenu,
    1128                                                MIT_END,
    1129                                                1001,
    1130                                                "Sort by index",
    1131                                                MIS_TEXT, 0);
    1132                             winhInsertMenuItem(hwndMenu,
    1133                                                MIT_END,
    1134                                                1002,
    1135                                                "Sort by source file",
    1136                                                MIS_TEXT, 0);
    1137                             cnrhShowContextMenu(WinWindowFromID(hwndClient, ID_MEMCNR),
    1138                                                 NULL,       // record
    1139                                                 hwndMenu,
    1140                                                 hwndClient);
    1141                         }
    1142                     }
    1143                 }
    1144             }
    1145         break; }
    1146 
    1147         case WM_COMMAND:
    1148             switch (SHORT1FROMMP(mp1))
    1149             {
    1150                 case 1001:  // sort by index
    1151                     WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
    1152                                CM_SORTRECORD,
    1153                                (MPARAM)mnu_fnCompareIndex,
    1154                                0);
    1155                 break;
    1156 
    1157                 case 1002:  // sort by source file
    1158                     WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
    1159                                CM_SORTRECORD,
    1160                                (MPARAM)mnu_fnCompareSourceFile,
    1161                                0);
    1162                 break;
    1163             }
    1164         break;
    1165 
    1166         case WM_CLOSE:
    1167             WinDestroyWindow(WinWindowFromID(hwndClient, ID_MEMCNR));
    1168             WinDestroyWindow(WinQueryWindow(hwndClient, QW_PARENT));
    1169             free(G_pszMemCnrTitle);
    1170             G_pszMemCnrTitle = NULL;
    1171         break;
    1172 
    1173         default:
    1174             mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
    1175     }
    1176 
    1177     return (mrc);
    1178 }
    1179 
    1180 /*
    1181  *@@ memdCreateMemDebugWindow:
    1182  *      creates a heap debugging window which
    1183  *      is a standard frame with a container,
    1184  *      listing all heap objects ever allocated.
    1185  *
    1186  *      The client of this standard frame is in
    1187  *      memd_fnwpMemDebug.
    1188  *
    1189  *      This thing lists all calls to malloc()
    1190  *      which were ever made, including the
    1191  *      source file and source line number which
    1192  *      made the call. Extreeeemely useful for
    1193  *      detecting memory leaks.
    1194  *
    1195  *      This only works if the memory functions
    1196  *      have been replaced with the debug versions
    1197  *      in this file.
    1198  */
    1199 
    1200 VOID memdCreateMemDebugWindow(VOID)
    1201 {
    1202     ULONG flStyle = FCF_TITLEBAR | FCF_SYSMENU | FCF_HIDEMAX
    1203                     | FCF_SIZEBORDER | FCF_SHELLPOSITION
    1204                     | FCF_NOBYTEALIGN | FCF_TASKLIST;
    1205     if (WinRegisterClass(WinQueryAnchorBlock(HWND_DESKTOP),
    1206                          "XWPMemDebug",
    1207                          memd_fnwpMemDebug, 0L, 0))
    1208     {
    1209         HWND hwndClient;
    1210         HWND hwndMemFrame = WinCreateStdWindow(HWND_DESKTOP,
    1211                                                0L,
    1212                                                &flStyle,
    1213                                                "XWPMemDebug",
    1214                                                "Allocated XWorkplace Memory Objects",
    1215                                                0L,
    1216                                                NULLHANDLE,     // resource
    1217                                                0,
    1218                                                &hwndClient);
    1219         if (hwndMemFrame)
    1220         {
    1221             WinSetWindowPos(hwndMemFrame,
    1222                             HWND_TOP,
    1223                             0, 0, 0, 0,
    1224                             SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE);
    1225         }
    1226     }
    1227 }
    1228 
    1229693#else
    1230694void memdDummy(void)
Note: See TracChangeset for help on using the changeset viewer.