home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / LYLeaks.c < prev    next >
C/C++ Source or Header  |  1998-03-25  |  16KB  |  608 lines

  1. /*
  2. **    Copyright (c) 1994, University of Kansas, All Rights Reserved
  3. **
  4. **    This code will be used only if LY_FIND_LEAKS is defined.
  5. */
  6.  
  7. /*
  8. **    Disable the overriding of the memory routines for this file.
  9. */
  10. #define NO_MEMORY_TRACKING
  11.  
  12. #include <HTUtils.h>
  13. #include <tcp.h>
  14. #include <LYexit.h>
  15. #include <LYLeaks.h>
  16. #include <LYUtils.h>
  17. #include <ctype.h>
  18. /*#include <stdio.h> included by HTUtils.h -- FM */
  19.  
  20. #define FREE(x) if (x) {free(x); x = NULL;}
  21.  
  22. PRIVATE AllocationList *ALp_RunTimeAllocations = NULL;
  23.  
  24. PRIVATE void AddToList PARAMS((
  25.     AllocationList *    ALp_new));
  26. PRIVATE AllocationList *FindInList PARAMS((
  27.     void *            vp_find));
  28. PRIVATE void RemoveFromList PARAMS((
  29.     AllocationList *    ALp_del));
  30.  
  31. /*
  32. **  Purpose:    Print a report of all memory left unallocated by
  33. **        Lynx code or attempted unallocations on
  34. **        pointers that are not valid and then free
  35. **        all unfreed memory.
  36. **  Arguments:        void
  37. **  Return Value:    void
  38. **  Remarks/Portability/Dependencies/Restrictions:
  39. **        This function should be registered for execution with the
  40. **        atexit (stdlib.h) function as the first statement
  41. **        in main.
  42. **        All output of this function is sent to the file defined in
  43. **        the header LYLeaks.h (LEAKAGE_SINK).
  44. **  Revision History:
  45. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  46. **    10-30-97    modified to handle StrAllocCopy() and
  47. **              StrAllocCat(). - KW & FM
  48. */
  49. PUBLIC void LYLeaks NOARGS
  50. {
  51.     AllocationList *ALp_head;
  52.     size_t st_total = (size_t)0;
  53.     FILE *Fp_leakagesink;
  54.  
  55.     /*
  56.      *    Open the leakage sink to take all the output.
  57.      *    Recreate the file each time.
  58.      *    Do nothing if unable to open the file.
  59.      */
  60.     Fp_leakagesink = LYNewTxtFile(LEAKAGE_SINK);
  61.     if (Fp_leakagesink == NULL) {
  62.     return;
  63.     }
  64.  
  65.     while (ALp_RunTimeAllocations != NULL) {
  66.     /*
  67.      *  Take the head off of the run time allocation list.
  68.      */
  69.     ALp_head = ALp_RunTimeAllocations;
  70.     ALp_RunTimeAllocations = ALp_head->ALp_Next;
  71.  
  72.     /*
  73.      *  Print the type of leak/error.
  74.      *  Free off memory when we no longer need it.
  75.      */
  76.     if (ALp_head->vp_Alloced == NULL) {
  77.         /*
  78.          *    If there is realloc information on the
  79.          *    bad request, then it was a bad pointer
  80.          *    value in a realloc statement.
  81.          */
  82.         fprintf(Fp_leakagesink,
  83.             "Invalid pointer detected.\n");
  84.         fprintf(Fp_leakagesink,
  85.             "Pointer:\t%p\n", ALp_head->vp_BadRequest);
  86.  
  87.         /*
  88.          *    Don't free the bad request, it is an invalid pointer.
  89.          *    If the free source information is empty, we
  90.          *    should check the realloc information
  91.          *    too since it can get passed bad pointer
  92.          *    values also.
  93.          */
  94.         if (ALp_head->SL_memory.cp_FileName == NULL) {
  95.         fprintf(Fp_leakagesink, "FileName:\t%s\n",
  96.             ALp_head->SL_realloc.cp_FileName);
  97.         fprintf(Fp_leakagesink, "LineCount:\t%d\n",
  98.             ALp_head->SL_realloc.ssi_LineNumber);
  99.         } else {
  100.         fprintf(Fp_leakagesink, "FileName:\t%s\n",
  101.                 ALp_head->SL_memory.cp_FileName);
  102.         fprintf(Fp_leakagesink, "LineCount:\t%d\n",
  103.                 ALp_head->SL_memory.ssi_LineNumber);
  104.         }
  105.     } else {
  106.         size_t i_counter;
  107.  
  108.         /*
  109.          *    Increment the count of total memory lost and
  110.          *    then print the information.
  111.          */
  112.         st_total += ALp_head->st_Bytes;
  113.  
  114.         fprintf(Fp_leakagesink, "Memory leak detected.\n");
  115.         fprintf(Fp_leakagesink, "Pointer:\t%p\n", ALp_head->vp_Alloced);
  116.         fprintf(Fp_leakagesink, "Contains:\t");
  117.         for (i_counter = 0;
  118.          i_counter < ALp_head->st_Bytes &&
  119.          i_counter < MAX_CONTENT_LENGTH;
  120.          i_counter++) {
  121.         if (isprint(((char *)(ALp_head->vp_Alloced))[i_counter])) {
  122.             fprintf(Fp_leakagesink, "%c",
  123.                 ((char *)(ALp_head->vp_Alloced))[i_counter]);
  124.         } else {
  125.             fprintf(Fp_leakagesink, "|");
  126.         }
  127.         }
  128.         fprintf(Fp_leakagesink, "\n");
  129.         FREE(ALp_head->vp_Alloced);
  130.         fprintf(Fp_leakagesink, "ByteSize:\t%d\n",
  131.                     (int)(ALp_head->st_Bytes));
  132.         fprintf(Fp_leakagesink, "FileName:\t%s\n",
  133.                     ALp_head->SL_memory.cp_FileName);
  134.         fprintf(Fp_leakagesink, "LineCount:\t%d\n",
  135.                     ALp_head->SL_memory.ssi_LineNumber);
  136.         /*
  137.          *    Give the last time the pointer was realloced
  138.          *    if it happened also.
  139.          */
  140.         if (ALp_head->SL_realloc.cp_FileName != NULL) {
  141.         fprintf(Fp_leakagesink, "realloced:\t%s\n",
  142.             ALp_head->SL_realloc.cp_FileName);
  143.         fprintf(Fp_leakagesink, "LineCount:\t%d\n",
  144.             ALp_head->SL_realloc.ssi_LineNumber);
  145.         }
  146.     }
  147.  
  148.     /*
  149.      *  Create a blank line and release the memory held
  150.      *  by the item.
  151.      */
  152.     fprintf(Fp_leakagesink, "\n");
  153.     FREE(ALp_head);
  154.     }
  155.  
  156.     /*
  157.      *    Give a grand total of the leakage.
  158.      *    Close the output file.
  159.      */
  160.     fprintf(Fp_leakagesink, "\nTotal memory leakage this run:\t%u\n",
  161.         (unsigned)st_total);
  162.     fclose(Fp_leakagesink);
  163. #ifdef VMS
  164.     {
  165.     char VMSfilename[256];
  166.     /*
  167.      *  Purge lower versions of the file.
  168.      */
  169.     sprintf(VMSfilename, "%s;-1", LEAKAGE_SINK);
  170.     while (remove(VMSfilename) == 0)
  171.         ;
  172.     /*
  173.      *  Reset version number.
  174.      */
  175.     sprintf(VMSfilename, "%s;1", LEAKAGE_SINK);
  176.     rename(LEAKAGE_SINK, VMSfilename);
  177.     }
  178. #endif /* VMS */
  179. }
  180.  
  181. /*
  182. **  Purpose:    Capture allocations using malloc (stdlib.h) and track
  183. **        the information in a list.
  184. **  Arguments:    st_bytes    The size of the allocation requested
  185. **                in bytes.
  186. **        cp_File     The file from which the request for
  187. **                allocation came from.
  188. **        ssi_Line    The line number in cp_File where the
  189. **                allocation request came from.
  190. **  Return Value:    void *    A pointer to the allocated memory or NULL on
  191. **                failure as per malloc (stdlib.h)
  192. **  Remarks/Portability/Dependencies/Restrictions:
  193. **        If no memory is allocated, then no entry is added to the
  194. **        allocation list.
  195. **  Revision History:
  196. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  197. */
  198. PUBLIC void *LYLeakMalloc ARGS3(
  199.     size_t,     st_bytes,
  200.     CONST char *,    cp_File,
  201.     CONST short,    ssi_Line)
  202. {
  203.     /*
  204.      *    Do the actual allocation.
  205.      */
  206.     void *vp_malloc = (void *)malloc(st_bytes);
  207.  
  208.     /*
  209.      *    Only on successful allocation do we track any information.
  210.      */
  211.     if (vp_malloc != NULL) {
  212.     /*
  213.      *  Further allocate memory to store the information.
  214.      *  Just return on failure to allocate more.
  215.      */
  216.     AllocationList *ALp_new =
  217.             (AllocationList *)calloc(1, sizeof(AllocationList));
  218.  
  219.     if (ALp_new == NULL) {
  220.         return(vp_malloc);
  221.     }
  222.     /*
  223.      *  Copy over the relevant information.
  224.      *  There is no need to allocate more memory for the
  225.      *  file name as it is a static string anyhow.
  226.      */
  227.     ALp_new->vp_Alloced = vp_malloc;
  228.     ALp_new->st_Bytes = st_bytes;
  229.     ALp_new->SL_memory.cp_FileName = cp_File;
  230.     ALp_new->SL_memory.ssi_LineNumber = ssi_Line;
  231.  
  232.     /*
  233.      *  Add the new item to the allocation list.
  234.      */
  235.     AddToList(ALp_new);
  236.     }
  237.  
  238.     return(vp_malloc);
  239. }
  240.  
  241. /*
  242. **  Purpose:    Capture allocations by calloc (stdlib.h) and
  243. **        save relevant information in a list.
  244. **  Arguments:    st_number    The number of items to allocate.
  245. **        st_bytes    The size of each item.
  246. **        cp_File     The file which wants to allocation.
  247. **        ssi_Line    The line number in cp_File requesting
  248. **                the allocation.
  249. **  Return Value:    void *    The allocated memory, or NULL on failure as
  250. **                per calloc (stdlib.h)
  251. **  Remarks/Portability/Dependencies/Restrictions:
  252. **        If no memory can be allocated, then no entry will be added
  253. **        to the list.
  254. **  Revision History:
  255. **        05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  256. */
  257. PUBLIC void *LYLeakCalloc ARGS4(
  258.     size_t,     st_number,
  259.     size_t,     st_bytes,
  260.     CONST char *,    cp_File,
  261.     CONST short,    ssi_Line)
  262. {
  263.     /*
  264.      *    Allocate the requested memory.
  265.      */
  266.     void *vp_calloc = (void *)calloc(st_number, st_bytes);
  267.  
  268.     /*
  269.      *    Only if the allocation was a success do we track information.
  270.      */
  271.     if (vp_calloc != NULL) {
  272.     /*
  273.      *  Allocate memory for the item to be in the list.
  274.      *  If unable, just return.
  275.      */
  276.     AllocationList *ALp_new =
  277.             (AllocationList *)calloc(1, sizeof(AllocationList));
  278.  
  279.     if (ALp_new == NULL) {
  280.         return(vp_calloc);
  281.     }
  282.  
  283.     /*
  284.      *  Copy over the relevant information.
  285.      *  There is no need to allocate memory for the file
  286.      *  name as it is a static string anyway.
  287.      */
  288.     ALp_new->vp_Alloced = vp_calloc;
  289.     ALp_new->st_Bytes = (st_number * st_bytes);
  290.     ALp_new->SL_memory.cp_FileName = cp_File;
  291.     ALp_new->SL_memory.ssi_LineNumber = ssi_Line;
  292.  
  293.     /*
  294.      *    Add the item to the allocation list.
  295.      */
  296.     AddToList(ALp_new);
  297.     }
  298.  
  299.     return(vp_calloc);
  300. }
  301.  
  302. /*
  303. **  Purpose:    Capture any realloc (stdlib.h) calls in order to
  304. **        properly keep track of our run time allocation
  305. **        table.
  306. **  Arguments:    vp_Alloced    The previously allocated block of
  307. **                memory to resize.  If NULL,
  308. **                realloc works just like
  309. **                malloc.
  310. **        st_newBytes    The new size of the chunk of memory.
  311. **        cp_File     The file containing the realloc.
  312. **        ssi_Line    The line containing the realloc in cp_File.
  313. **  Return Value:    void *    The new pointer value (could be the same) or
  314. **                NULL if unable to resize (old block
  315. **                still exists).
  316. **  Remarks/Portability/Dependencies/Restrictions:
  317. **        If unable to resize vp_Alloced, then no change in the
  318. **        allocation list will be made.
  319. **        If vp_Alloced is an invalid pointer value, the program will
  320. **        exit after one last entry is added to the allocation list.
  321. **  Revision History:
  322. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  323. */
  324. PUBLIC void *LYLeakRealloc ARGS4(
  325.     void *,     vp_Alloced,
  326.     size_t,     st_newBytes,
  327.     CONST char *,    cp_File,
  328.     CONST short,    ssi_Line)
  329. {
  330.     void *vp_realloc;
  331.     AllocationList *ALp_renew;
  332.  
  333.     /*
  334.      *    If we are asked to resize a NULL pointer, this is just a
  335.      *    malloc call.
  336.      */
  337.     if (vp_Alloced == NULL) {
  338.     return(LYLeakMalloc(st_newBytes, cp_File, ssi_Line));
  339.     }
  340.  
  341.     /*
  342.      *    Find the current vp_Alloced block in the list.
  343.      *    If NULL, this is an invalid pointer value.
  344.      */
  345.     ALp_renew = FindInList(vp_Alloced);
  346.     if (ALp_renew == NULL) {
  347.     /*
  348.      *  Track the invalid pointer value and then exit.
  349.      *  If unable to allocate, just exit.
  350.      */
  351.     auto AllocationList *ALp_new =
  352.                  (AllocationList *)calloc(1,
  353.                               sizeof(AllocationList));
  354.  
  355.     if (ALp_new == NULL) {
  356.         exit(-1);
  357.     }
  358.  
  359.     /*
  360.      *  Set the information up; no need to allocate file name
  361.      *  since it is a static string.
  362.      */
  363.     ALp_new->vp_Alloced = NULL;
  364.     ALp_new->vp_BadRequest = vp_Alloced;
  365.     ALp_new->SL_realloc.cp_FileName = cp_File;
  366.     ALp_new->SL_realloc.ssi_LineNumber = ssi_Line;
  367.  
  368.     /*
  369.      *  Add the item to the list.
  370.      *  Exit.
  371.      */
  372.     AddToList(ALp_new);
  373.     exit(-1);
  374.     }
  375.  
  376.     /*
  377.      *    Perform the resize.
  378.      *    If not NULL, record the information.
  379.      */
  380.     vp_realloc = (void *)realloc(vp_Alloced, st_newBytes);
  381.     if (vp_realloc != NULL) {
  382.     ALp_renew->vp_Alloced = vp_realloc;
  383.     ALp_renew->st_Bytes = st_newBytes;
  384.  
  385.     /*
  386.      *  Update the realloc information, too.
  387.      *  No need to allocate file name, static string.
  388.      */
  389.     ALp_renew->SL_realloc.cp_FileName = cp_File;
  390.     ALp_renew->SL_realloc.ssi_LineNumber = ssi_Line;
  391.     }
  392.  
  393.     return(vp_realloc);
  394. }
  395.  
  396. /*
  397. **  Purpose:    Capture all requests to free information and also
  398. **        remove items from the allocation list.
  399. **  Arguments:    vp_Alloced    The memory to free.
  400. **        cp_File     The file calling free.
  401. **        ssi_Line    The line of cp_File calling free.
  402. **  Return Value:    void
  403. **  Remarks/Portability/Dependencies/Restrictions:
  404. **        If the pointer value is invalid, then an item will be added
  405. **        to the list and nothing else is done.
  406. **        I really like the name of this function and one day hope
  407. **        that Lynx is Leak Free.
  408. **  Revision History:
  409. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  410. */
  411. PUBLIC void LYLeakFree ARGS3(
  412.     void *,     vp_Alloced,
  413.     CONST char *,    cp_File,
  414.     CONST short,    ssi_Line)
  415. {
  416.     AllocationList *ALp_free;
  417.  
  418.     /*
  419.      *    Find the pointer in the allocated list.
  420.      *    If not found, bad pointer.
  421.      *    If found, free list item and vp_Allloced.
  422.      */
  423.     ALp_free = FindInList(vp_Alloced);
  424.     if (ALp_free == NULL) {
  425.     /*
  426.      *  Create the final entry before exiting marking this error.
  427.      *  If unable to allocate more memory just exit.
  428.      */
  429.     AllocationList *ALp_new =
  430.             (AllocationList *)calloc(1,
  431.                          sizeof(AllocationList));
  432.  
  433.     if (ALp_new == NULL) {
  434.         exit(-1);
  435.     }
  436.  
  437.     /*
  438.      *  Set up the information, no memory need be allocated
  439.      *  for the file name since it is a static string.
  440.      */
  441.     ALp_new->vp_Alloced = NULL;
  442.     ALp_new->vp_BadRequest = vp_Alloced;
  443.     ALp_new->SL_memory.cp_FileName = cp_File;
  444.     ALp_new->SL_memory.ssi_LineNumber = ssi_Line;
  445.  
  446.     /*
  447.      *  Add the entry to the list and then return.
  448.      */
  449.     AddToList(ALp_new);
  450.     return;
  451.     } else {
  452.     /*
  453.      *  Free off the memory.
  454.      *  Take entry out of allocation list.
  455.      */
  456.     RemoveFromList(ALp_free);
  457.     FREE(ALp_free);
  458.     FREE(vp_Alloced);
  459.     }
  460. }
  461.  
  462. /*
  463. **  Allocates a new copy of a string, and returns it.
  464. **  Tracks allocations by using other LYLeakFoo functions.
  465. **  Equivalent to HTSACopy in HTUtils.c - KW
  466. */
  467. PUBLIC char * LYLeakSACopy ARGS4(
  468.     char **,    dest,
  469.     CONST char *,    src,
  470.     CONST char *,    cp_File,
  471.     CONST short,    ssi_Line)
  472. {
  473.     if (*dest) {
  474.     LYLeakFree(*dest, cp_File, ssi_Line);
  475.     *dest = NULL;
  476.     }
  477.     if (src) {
  478.     *dest = (char *)LYLeakMalloc(strlen(src) + 1, cp_File, ssi_Line);
  479.     if (*dest == NULL)
  480.         outofmem(__FILE__, "LYLeakSACopy");
  481.     strcpy (*dest, src);
  482.     }
  483.     return *dest;
  484. }
  485.  
  486. /*
  487. **  String Allocate and Concatenate.
  488. **  Tracks allocations by using other LYLeakFoo functions.
  489. **  Equivalent to HTSACat in HTUtils.c - KW
  490. */
  491. PUBLIC char * LYLeakSACat ARGS4(
  492.     char **,    dest,
  493.     CONST char *,    src,
  494.     CONST char *,    cp_File,
  495.     CONST short,    ssi_Line)
  496. {
  497.     if (src && *src) {
  498.     if (*dest) {
  499.         int length = strlen(*dest);
  500.         *dest = (char *)LYLeakRealloc(*dest,
  501.                       (length + strlen(src) + 1),
  502.                       cp_File,
  503.                       ssi_Line);
  504.         if (*dest == NULL)
  505.         outofmem(__FILE__, "LYLeakSACat");
  506.         strcpy (*dest + length, src);
  507.     } else {
  508.         *dest = (char *)LYLeakMalloc((strlen(src) + 1),
  509.                      cp_File,
  510.                      ssi_Line);
  511.         if (*dest == NULL)
  512.         outofmem(__FILE__, "LYLeakSACat");
  513.         strcpy (*dest, src);
  514.     }
  515.     }
  516.     return *dest;
  517. }
  518.  
  519. /*
  520. **  Purpose:    Add a new allocation item to the list.
  521. **  Arguments:        ALp_new The new item to add.
  522. **  Return Value:    void
  523. **  Remarks/Portability/Dependencies/Restrictions:
  524. **        Static function made to make code reusable in projects beyond
  525. **        Lynx (some might ask why not use HTList).
  526. **  Revision History:
  527. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  528. */
  529. PRIVATE void AddToList ARGS1(
  530.     AllocationList *,    ALp_new)
  531. {
  532.     /*
  533.      *    Just make this the first item in the list.
  534.      */
  535.     ALp_new->ALp_Next = ALp_RunTimeAllocations;
  536.     ALp_RunTimeAllocations = ALp_new;
  537. }
  538.  
  539. /*
  540. **  Purpose:    Find the place in the list where vp_find is currently
  541. **        tracked.
  542. **  Arguments:        vp_find A pointer to look for in the list.
  543. **  Return Value:    AllocationList *    Either vp_find's place in the
  544. **                        list or NULL if not found.
  545. **  Remarks/Portability/Dependencies/Restrictions:
  546. **        Static function made to make code reusable in projects outside
  547. **        of Lynx (some might ask why not use HTList).
  548. **  Revision History:
  549. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  550. */
  551. PRIVATE AllocationList *FindInList ARGS1(
  552.     void *,     vp_find)
  553. {
  554.     AllocationList *ALp_find = ALp_RunTimeAllocations;
  555.  
  556.     /*
  557.      *    Go through the list of allocated pointers until end of list
  558.      *        or vp_find is found.
  559.      */
  560.     while (ALp_find != NULL) {
  561.     if (ALp_find->vp_Alloced == vp_find) {
  562.         break;
  563.     }
  564.     ALp_find = ALp_find->ALp_Next;
  565.     }
  566.  
  567.     return(ALp_find);
  568. }
  569.  
  570. /*
  571. **  Purpose:    Remove the specified item from the list.
  572. **  Arguments:        ALp_del The item to remove from the list.
  573. **  Return Value:    void
  574. **  Remarks/Portability/Dependencies/Restrictions:
  575. **        Static function made to make code reusable in projects outside
  576. **        of Lynx (some might ask why not use HTList).
  577. **  Revision History:
  578. **    05-26-94    created Lynx 2-3-1 Garrett Arch Blythe
  579. */
  580. PRIVATE void RemoveFromList ARGS1(
  581.     AllocationList *,    ALp_del)
  582. {
  583.     AllocationList *ALp_findbefore = ALp_RunTimeAllocations;
  584.  
  585.     /*
  586.      *    There is one special case, where the item to remove is the
  587.      *        first in the list.
  588.      */
  589.     if (ALp_del == ALp_findbefore) {
  590.     ALp_RunTimeAllocations = ALp_del->ALp_Next;
  591.     return;
  592.     }
  593.  
  594.     /*
  595.      *    Loop through checking all of the next values, if a match
  596.      *    don't continue.  Always assume the item will be found.
  597.      */
  598.     while (ALp_findbefore->ALp_Next != ALp_del) {
  599.     ALp_findbefore = ALp_findbefore->ALp_Next;
  600.     }
  601.  
  602.     /*
  603.      *    We are one item before the one to get rid of.
  604.      *    Get rid of it.
  605.      */
  606.     ALp_findbefore->ALp_Next = ALp_del->ALp_Next;
  607. }
  608.