home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Science / Science.zip / imdisp79.zip / MSHELL.C < prev    next >
C/C++ Source or Header  |  1993-02-15  |  12KB  |  609 lines

  1. /*----------------------------------------------------------------------
  2.  *++
  3.  *  mshell.c
  4.  *  Memory management utilities
  5.  *
  6.  *  Description
  7.  *
  8.  *    mshell.c contains routines to protect the programmer
  9.  *    from errors in calling memory allocation/free routines.
  10.  *    The programmer must use the memory calls defined
  11.  *    in mshell.h. When these calls are used, the
  12.  *    allocation routines in this module add a data structure
  13.  *    to the top of allocated memory blocks which tags them as
  14.  *    legal memory blocks.
  15.  *
  16.  *    When the free routine is called, the memory block to
  17.  *    be freed is checked for legality tag.  If the block
  18.  *    is not legal, the memory list is dumped to stderr and
  19.  *    the program is terminated.
  20.  *
  21.  *  Compilation Options
  22.  *
  23.  *    MEM_LIST    Link all allocated memory blocks onto
  24.  *            an internal list. The list can be
  25.  *            displayed using Mem_Display().
  26.  *
  27.  *    MEM_WHERE    Save the file/line number of allocated
  28.  *            blocks in the header.
  29.  *            Requires that the compilier supports
  30.  *            __FILE__ and __LINE__ preprocessor
  31.  *            directives.
  32.  *            Also requires that the __FILE__ string
  33.  *            have a static or global scope.
  34.  *
  35.  *+-
  36.  *
  37.  *  $Log$
  38.  *    
  39.  *--
  40.  */
  41.  
  42. #define __MSHELL__
  43.  
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include "mshell.h"
  48. #include "imdef.h"
  49. #include "imdisp.h"
  50. #include "dispio.h"
  51.  
  52. /* Constants */
  53. /* --------- */
  54. #define MEMTAG    0xa55a            /* Value for mh_tag */
  55.  
  56. /* Structures */
  57. /* ---------- */
  58. typedef struct memnod            /* Memory block header info    */
  59.     {                /* ---------------------------- */
  60.     unsigned int    mh_tag ;    /* Special ident tag        */
  61.     size_t        mh_size ;    /* Size of allocation block    */
  62. #if defined(MEM_LIST)
  63.     struct memnod    *mh_next ;    /* Next memory block        */
  64.     struct memnod    *mh_prev ;    /* Previous memory block    */
  65. #endif
  66. #if defined(MEM_WHERE)
  67.     char        *mh_file ;    /* File allocation was from    */
  68.     unsigned int    mh_line ;    /* Line allocation was from    */
  69. #endif
  70.     } MEMHDR ;
  71.  
  72. /* Alignment macros */
  73. /* ---------------- */
  74. #define ALIGN_SIZE sizeof(double)
  75. #define HDR_SIZE sizeof(MEMHDR)
  76. #define RESERVE_SIZE (((HDR_SIZE+(ALIGN_SIZE-1))/ALIGN_SIZE) \
  77.             *ALIGN_SIZE)
  78.  
  79. /* Conversion macros */
  80. /* ----------------- */
  81. #define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
  82. #define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
  83.  
  84. /* Local variables */
  85. /* --------------- */
  86. static unsigned long    mem_size = 0 ;    /* Amount of memory used */
  87. #if defined(MEM_LIST)
  88. static MEMHDR    *memlist = NULL ;    /* List of memory blocks */
  89. #endif
  90.  
  91. /* Local functions */
  92. /* --------------- */
  93. void    mem_tag_err(void *, char *, int) ;    /* Tag error */
  94. #if defined(MEM_LIST)
  95. void    mem_list_add(MEMHDR *) ;        /* Add block to list */
  96. void    mem_list_delete(MEMHDR *) ;        /* Delete block from list */
  97. #define Mem_Tag_Err(a) mem_tag_err(a,fil,lin)
  98. #else
  99. #define Mem_Tag_Err(a) mem_tag_err(a,__FILE__,__LINE__)
  100. #endif
  101.  
  102. /************************************************************************/
  103. /**** Functions accessed only through macros ****************************/
  104. /************************************************************************/
  105.  
  106. /*----------------------------------------------------------------------
  107.  *+
  108.  *  mem_alloc
  109.  *  Allocate a memory block
  110.  *
  111.  *  Usage
  112.  *
  113.  *    void *
  114.  *    mem_alloc(
  115.  *    size_t        size
  116.  *    )
  117.  *
  118.  *  Parameters
  119.  *
  120.  *    size        Size of block in bytes to allocate
  121.  *
  122.  *  Return Value
  123.  *
  124.  *    Pointer to allocated memory block
  125.  *    NULL if not enough memory
  126.  *
  127.  *  Description
  128.  *
  129.  *    mem_alloc() makes a protected call to malloc()
  130.  *
  131.  *  Notes
  132.  *
  133.  *    Access this routine using the malloc() macro in mshell.h
  134.  *
  135.  *-
  136.  */
  137.  
  138. void *
  139. mem_alloc(
  140. #if defined(MEM_WHERE)
  141. size_t        size,
  142. char        *fil,
  143. int        lin
  144. #else
  145. size_t        size
  146. #endif
  147. )
  148.  
  149. {
  150. MEMHDR        *p ;
  151.  
  152. /* Allocate memory block */
  153. /* --------------------- */
  154. p = malloc(RESERVE_SIZE + size) ;
  155. if (p == NULL)
  156.     {
  157.     return NULL ;
  158.     }
  159.  
  160. /* Init header */
  161. /* ----------- */
  162. p->mh_tag = MEMTAG ;
  163. p->mh_size = size ;
  164. mem_size += size ;
  165. #if defined(MEM_WHERE)
  166. p->mh_file = fil ;
  167. p->mh_line = lin ;
  168. #endif
  169.  
  170. #if defined(MEM_LIST)
  171. mem_list_add(p) ;
  172. #endif
  173.  
  174. /* Return pointer to client data */
  175. /* ----------------------------- */
  176. return HDR_2_CLIENT(p) ;
  177. }
  178.  
  179. /*----------------------------------------------------------------------
  180.  *+
  181.  *  mem_realloc
  182.  *  Reallocate a memory block
  183.  *
  184.  *  Usage
  185.  *
  186.  *    void *
  187.  *    mem_realloc(
  188.  *    void        *ptr,
  189.  *    size_t         size
  190.  *    )
  191.  *
  192.  *  Parameters
  193.  *
  194.  *    ptr        Pointer to current block
  195.  *    size        Size to adjust block to
  196.  *
  197.  *  Return Value
  198.  *
  199.  *    Pointer to new memory block
  200.  *    NULL if memory cannot be reallocated
  201.  *
  202.  *  Description
  203.  *
  204.  *    mem_realloc() makes a protected call to realloc().
  205.  *
  206.  *  Notes
  207.  *
  208.  *    Access this routine using the realloc() macro in mshell.h
  209.  *
  210.  *-
  211.  */
  212.  
  213. void *
  214. mem_realloc(
  215. #if defined(MEM_WHERE)
  216. void        *ptr,
  217. size_t        size,
  218. char        *fil,
  219. int        lin
  220. #else
  221. void        *ptr,
  222. size_t        size
  223. #endif
  224. )
  225.  
  226. {
  227. MEMHDR        *p ;
  228.  
  229. /* Convert client pointer to header pointer */
  230. /* ---------------------------------------- */
  231. p = CLIENT_2_HDR(ptr) ;
  232.  
  233. /* Check for valid block */
  234. /* --------------------- */
  235. if (p->mh_tag != MEMTAG)
  236.     {
  237.     Mem_Tag_Err(p) ;
  238.     return NULL ;
  239.     }
  240.  
  241. /* Invalidate header */
  242. /* ----------------- */
  243. p->mh_tag = ~MEMTAG ;
  244. mem_size -= p->mh_size ;
  245.  
  246. #if defined(MEM_WHERE)
  247. mem_list_delete(p) ;    /* Remove block from list */
  248. #endif
  249.  
  250. /* Reallocate memory block */
  251. /* ----------------------- */
  252. p = (MEMHDR *) realloc(p, RESERVE_SIZE + size) ;
  253. if (p == NULL)
  254.     {
  255.     return NULL ;
  256.     }
  257.  
  258. /* Update header */
  259. /* ------------- */
  260. p->mh_tag = MEMTAG ;
  261. p->mh_size = size ;
  262. mem_size += size ;
  263. #if defined(MEM_LIST)
  264. p->mh_file = fil ;
  265. p->mh_line = lin ;
  266. #endif
  267.  
  268. #if defined(MEM_WHERE)
  269. mem_list_add(p) ;    /* Add block to list */
  270. #endif
  271.  
  272. /* Return pointer to client data */
  273. /* ----------------------------- */
  274. return HDR_2_CLIENT(p) ;
  275. }
  276.  
  277. /*----------------------------------------------------------------------
  278.  *+
  279.  *  mem_strdup
  280.  *  Save a string in dynamic memory
  281.  *
  282.  *  Usage
  283.  *
  284.  *    char *
  285.  *    mem_strdup(
  286.  *    char        *str
  287.  *    )
  288.  *
  289.  *  Parameters
  290.  *
  291.  *    str        String to save
  292.  *
  293.  *  Return Value
  294.  *
  295.  *    Pointer to allocated string
  296.  *    NULL if not enough memory
  297.  *
  298.  *  Description
  299.  *
  300.  *    mem_strdup() saves the specified string in dynamic memory.
  301.  *
  302.  *  Notes
  303.  *
  304.  *    Access this routine using the strdup() macro in mshell.h
  305.  *
  306.  *-
  307.  */
  308.  
  309. char *
  310. mem_strdup(
  311. #if defined(MEM_WHERE)
  312. char        *str,
  313. char        *fil,
  314. int        lin
  315. #else
  316. char        *str
  317. #endif
  318. )
  319.  
  320. {
  321. char * s ;
  322.  
  323. #if defined(MEM_WHERE)
  324. s = mem_alloc(strlen(str)+1, fil, lin) ;
  325. #else
  326. s = mem_alloc(strlen(str)+1) ;
  327. #endif
  328.  
  329. if (s != NULL)
  330.     {
  331.     strcpy(s, str) ;
  332.     }
  333.  
  334. return s ;
  335. }
  336.  
  337. /*----------------------------------------------------------------------
  338.  *+
  339.  *  mem_free
  340.  *  Free a memory block
  341.  *
  342.  *  Usage
  343.  *
  344.  *    void
  345.  *    mem_free(
  346.  *    void        *ptr
  347.  *    )
  348.  *
  349.  *  Parameters
  350.  *
  351.  *    ptr        Pointer to memory to free
  352.  *
  353.  *  Return Value
  354.  *
  355.  *    None
  356.  *
  357.  *  Description
  358.  *
  359.  *    mem_free() frees the specified memory block. The
  360.  *    block must be allocated using mem_alloc(), mem_realloc()
  361.  *    or mem_strdup().
  362.  *
  363.  *  Notes
  364.  *
  365.  *    Access this routine using the free() macro in mshell.h
  366.  *
  367.  *-
  368.  */
  369.  
  370. void
  371. mem_free(
  372. #if defined(MEM_WHERE)
  373. void        *ptr,
  374. char        *fil,
  375. int        lin
  376. #else
  377. void        *ptr
  378. #endif
  379. )
  380.  
  381. {
  382. MEMHDR         *p ;
  383.  
  384. /* Convert client pointer to header pointer */
  385. /* ---------------------------------------- */
  386. p = CLIENT_2_HDR(ptr) ;
  387.  
  388. /* Check for valid block */
  389. /* --------------------- */
  390. if (p->mh_tag != MEMTAG)
  391.     {
  392.     Mem_Tag_Err(p) ;
  393.     return ;
  394.     }
  395.  
  396. /* Invalidate header */
  397. /* ----------------- */
  398. p->mh_tag = ~MEMTAG ;
  399. mem_size -= p->mh_size ;
  400.  
  401. #if defined(MEM_LIST)
  402. mem_list_delete(p) ;    /* Remove block from list */
  403. #endif
  404.  
  405. /* Free memory block */
  406. /* ----------------- */
  407. free(p) ;
  408. }
  409.  
  410. /************************************************************************/
  411. /**** Functions accessed directly ***************************************/
  412. /************************************************************************/
  413.  
  414. /*----------------------------------------------------------------------
  415.  *+
  416.  *  Mem_Used
  417.  *  Return amount of memory currently allocated
  418.  *
  419.  *  Usage
  420.  *
  421.  *    unsigned long
  422.  *    Mem_Used(
  423.  *    )
  424.  *
  425.  *  Parameters
  426.  *
  427.  *    None.
  428.  *
  429.  *  Description
  430.  *
  431.  *    Mem_Used() returns the number of bytes currently allocated
  432.  *    using the memory management system. The value returned is
  433.  *    simply the sum of the size requests to allocation routines.
  434.  *    It does not reflect any overhead required by the memory
  435.  *    management system.
  436.  *
  437.  *  Notes
  438.  *
  439.  *    None
  440.  *
  441.  *-
  442.  */
  443.  
  444. unsigned long
  445. Mem_Used(
  446. void)
  447.  
  448. {
  449. return mem_size ;
  450. }
  451.  
  452. /*----------------------------------------------------------------------
  453.  *+
  454.  *  Mem_Display
  455.  *  Display memory allocation list
  456.  *
  457.  *  Usage
  458.  *
  459.  *    void
  460.  *    Mem_Display(
  461.  *    FILE        *fp
  462.  *    )
  463.  *
  464.  *  Parameters
  465.  *
  466.  *    fp        File to output data to
  467.  *
  468.  *  Description
  469.  *
  470.  *    Mem_Display() displays the contents of the memory
  471.  *    allocation list.
  472.  *
  473.  *    This function is a no-op if MEM_LIST is not defined.
  474.  *
  475.  *  Notes
  476.  *
  477.  *    None
  478.  *
  479.  *-
  480.  */
  481.  
  482. void
  483. Mem_Display(
  484. FILE        *fp
  485. )
  486.  
  487. {
  488. #if defined(MEM_LIST)
  489. MEMHDR        *p ;
  490. int        idx ;
  491.  
  492. #if defined(MEM_WHERE)
  493. fprintf(fp, "Index   Size  File(Line) - total size %lu\n", mem_size) ;
  494. #else
  495. fprintf(fp, "Index   Size - total size %lu\n", mem_size) ;
  496. #endif
  497.  
  498. idx = 0 ;
  499. p = memlist ;
  500. while (p != NULL)
  501.     {
  502.     fprintf(fp, "%-5d %6u", idx++, p->mh_size) ;
  503. #if defined(MEM_WHERE)
  504.     fprintf(fp, "  %s(%d)", p->mh_file, p->mh_line) ;
  505. #endif
  506.     if (p->mh_tag != MEMTAG)
  507.         {
  508.         fprintf(fp, " INVALID") ;
  509.         }
  510.     fprintf(fp, "\n") ;
  511.     p = p->mh_next ;
  512.     }
  513. #else
  514. fprintf(fp, "Memory list not compiled (MEM_LIST not defined)\n") ;
  515. #endif
  516. }
  517.  
  518. /************************************************************************/
  519. /**** Memory list manipulation functions ********************************/
  520. /************************************************************************/
  521.  
  522. /*
  523.  * mem_list_add()
  524.  * Add block to list
  525.  */
  526.  
  527. #if defined(MEM_LIST)
  528. static void
  529. mem_list_add(
  530. MEMHDR    *p
  531. )
  532.  
  533. {
  534. p->mh_next = memlist ;
  535. p->mh_prev = NULL ;
  536. if (memlist != NULL)
  537.     {
  538.     memlist->mh_prev = p ;
  539.     }
  540. memlist = p ;
  541.  
  542. #if defined(DEBUG_LIST)
  543. printf("mem_list_add()\n") ;
  544. Mem_Display(stdout) ;
  545. #endif
  546. }
  547. #endif
  548.  
  549. /*----------------------------------------------------------------------*/
  550.  
  551. /*
  552.  * mem_list_delete()
  553.  * Delete block from list
  554.  */
  555.  
  556. #if defined(MEM_LIST)
  557. static void
  558. mem_list_delete(
  559. MEMHDR    *p
  560. )
  561.  
  562. {
  563. if (p->mh_next != NULL)
  564.     {
  565.     p->mh_next->mh_prev = p->mh_prev ;
  566.     }
  567. if (p->mh_prev != NULL)
  568.     {
  569.     p->mh_prev->mh_next = p->mh_next ;
  570.     }
  571.     else
  572.     {
  573.     memlist = p->mh_next ;
  574.     }
  575.  
  576. #if defined(DEBUG_LIST)
  577. printf("mem_list_delete()\n") ;
  578. Mem_Display(stdout) ;
  579. #endif
  580. }
  581. #endif
  582.  
  583. /************************************************************************/
  584. /**** Error display *****************************************************/
  585. /************************************************************************/
  586.  
  587. /*
  588.  *  mem_tag_err()
  589.  *  Display memory tag error
  590.  */
  591.  
  592. static void
  593. mem_tag_err(
  594. void        *p,
  595. char        *fil,
  596. int        lin
  597. )
  598.  
  599. {
  600. DisplayOff();
  601. fprintf(stderr, "Memory tag error - %p - %s(%d)\n", p, fil, lin) ;
  602. #if defined(MEM_LIST)
  603. Mem_Display(stderr) ;
  604. #endif
  605. exit(1) ;
  606. }
  607.  
  608. /*----------------------------------------------------------------------*/
  609.