home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 06 / dmalloc.c < prev    next >
Text File  |  1979-12-31  |  9KB  |  283 lines

  1.                              Listing 1 -- dmalloc.c
  2.    ____________________________________________________________________________
  3.   1| #include <stdio.h>
  4.   2| #include <stdlib.h>     /* for prototypes only  */
  5.   3| #include <malloc.h>     /* for prototypes only  */
  6.   4| #include <string.h>     /* for prototypes only  */
  7.   5| #include <dos.h>        /* SREGS definition     */
  8.   6| 
  9.   7| /* DMALLOC.C    Debugging versions of malloc and free for
  10.   8|  *              the compact model.
  11.   9|  */
  12.  10| 
  13.  11| #define MAXPTR 2048               /* max # of pointers to check */
  14.  12| 
  15.  13| static char huge*    *Pointers = NULL;
  16.  14| static int           Nel = 0;          /*# elements in Pointers */
  17.  15| static int           Debugging_on = 0;
  18.  16| static unsigned long Total_mem = 0L;
  19.  17| 
  20.  18| /*------------------------------------------------------------*/
  21.  19| int     malloc_checking   ( int on                      );
  22.  20| void    *dmalloc          ( unsigned size               );
  23.  21| void    *dcalloc          ( size_t n, size_t size       );
  24.  22| void    dfree             ( char huge* p                );
  25.  23| void    *find_in_table    ( char huge* key, int *found  );
  26.  24| void    add_to_table      ( char huge* p                );
  27.  25| int     remove_from_table ( char huge* p                );
  28.  26| unsigned long memory_used ( void                        );
  29.  27| /*------------------------------------------------------------*/
  30.  28| 
  31.  29| int     malloc_checking( on )
  32.  30| {
  33.  31|     /* Call this routine with a true argument to enable the
  34.  32|      * debugging features. Calling it with a false argument
  35.  33|      * frees all memory used for the checking.
  36.  34|      */
  37.  35|     
  38.  36|     if( !(Debugging_on = on) )
  39.  37|     {
  40.  38|         Nel = 0;
  41.  39|         if( Pointers )
  42.  40|             free( Pointers );
  43.  41|         Pointers = NULL;
  44.  42|     }
  45.  43|     else
  46.  44|     {
  47.  45|         if( !Pointers  &&
  48.  46|             !(Pointers = malloc(MAXPTR * sizeof(*Pointers))) )
  49.  47|         {
  50.  48|                 fprintf(stderr, "No memory for pointer checking\n");
  51.  49|                 return 0;
  52.  50|         }
  53.  51|     }
  54.  52| 
  55.  53|     return 1;
  56.  54| }
  57.  55| 
  58.  56| /*------------------------------------------------------------*/
  59.  57| 
  60.  58| unsigned long   memory_used()
  61.  59| {
  62.  60|     return Total_mem;
  63.  61| }
  64.  62| 
  65.  63| /*------------------------------------------------------------*/
  66.  64| 
  67.  65| void    *dcalloc( n, size )
  68.  66| size_t n, size;
  69.  67| {
  70.  68|     void        *p;
  71.  69| 
  72.  70|     if( p = dmalloc( size *= n ) )
  73.  71|         memset( p, 0, size );
  74.  72| 
  75.  73|     return p;
  76.  74| }
  77.  75| 
  78.  76| /*------------------------------------------------------------*/
  79.  77| 
  80.  78| void    *dmalloc( size )
  81.  79| unsigned size;
  82.  80| {
  83.  81|     /* Debbugging version of malloc. If debugging is enabled,
  84.  82|      * put the malloced pointer into the Pointers table before
  85.  83|      * returning it.
  86.  84|      */
  87.  85| 
  88.  86|     void        huge* p;
  89.  87| 
  90.  88|     Total_mem += size;
  91.  89| 
  92.  90|     if( !Debugging_on )
  93.  91|         return malloc( size );
  94.  92| 
  95.  93|     if( !(p = (void huge*) malloc( size )) )
  96.  94|     {
  97.  95|         fprintf(stderr,"Malloc out of memory, returning NULL\n");
  98.  96|         return NULL;
  99.  97|     }
  100.  98| 
  101.  99|     fprintf( stderr, "malloc(%u) = %p\n", size, p );
  102. 100|     add_to_table( p );
  103. 101|     return p;
  104. 102| }
  105. 103| 
  106. 104| /*------------------------------------------------------------*/
  107. 105| 
  108. 106| void    dfree( p )
  109. 107| char    huge* p;
  110. 108| {
  111. 109|     /* Debugging verion of free(). If debugging is enabled,
  112. 110|      * check that the returned pointer is in the Pointers[]
  113. 111|      * table before allowing it to be freed(). The return-
  114. 112|      * address computation is far from portable, but it's
  115. 113|      * useful nonetheless.
  116. 114|      */
  117. 115| 
  118. 116|     struct SREGS  seg;
  119. 117| 
  120. 118|     Total_mem -= _msize( p );
  121. 119| 
  122. 120|     if( !Debugging_on )
  123. 121|     {
  124. 122|         free( p );
  125. 123|         return;
  126. 124|     }
  127. 125|  
  128. 126|     if( !remove_from_table(p) )
  129. 127|     {
  130. 128|         segread( &seg );
  131. 129|         fprintf( stderr,"free() [Called from %04x:%04x]: BAD POINTER %p\n",
  132. 130|                            seg.cs, ((void(**)())( &p ))[-1], p);
  133. 131|         exit( 1 );
  134. 132|     }
  135. 133|     else
  136. 134|     {
  137. 135|         free( p );
  138. 136|         fprintf( stderr, "free(%p) successful\n", p );
  139. 137|     }
  140. 138| }
  141. 139| 
  142. 140| /*------------------------------------------------------------*/
  143. 141| 
  144. 142| static   void    *find_in_table( key, found )
  145. 143| char     huge* key;
  146. 144| int      *found;        /* set to 1 if found */
  147. 145| {
  148. 146|     /* Do a binary search in Pointers for key. If it's there
  149. 147|      * set *found to true and return a pointer to it; otherwise,
  150. 148|      * set *found to false and return a pointer to the place
  151. 149|      * in the table that it should go.
  152. 150|      */
  153. 151| 
  154. 152|     char huge*  *p;     /* Pointer to middle element      */
  155. 153|     char huge*  *array; /* Pointer to base of array       */
  156. 154|     int         mid;    /* Array index of middle element  */
  157. 155|     int         size;
  158. 156| 
  159. 157|     *found = 0;
  160. 158|     if( !(size = Nel) )
  161. 159|         return Pointers;
  162. 160| 
  163. 161|     array  = Pointers;
  164. 162| 
  165. 163|     while( size > 0 )
  166. 164|     {
  167. 165|         mid = size  >> 1  ;
  168. 166|         p = array + mid ;
  169. 167| 
  170. 168|         if ( key == *p )
  171. 169|         {
  172. 170|             *found = 1;
  173. 171|             return p;
  174. 172|         }
  175. 173|         else if (  key <  *p )
  176. 174|         {
  177. 175|             size = mid ;
  178. 176|         }
  179. 177|         else
  180. 178|         {
  181. 179|             array = p + 1;
  182. 180|             size -= mid+1;
  183. 181|         }
  184. 182|     }
  185. 183| 
  186. 184|     return (void *)( *p > key ? p : p + 1 );
  187. 185| }
  188. 186| 
  189. 187| /*------------------------------------------------------------*/
  190. 188| 
  191. 189| static  void    add_to_table(p)
  192. 190| char    huge* p;
  193. 191| {
  194. 192|     /* Add p to the Pointers table. If it's allready there
  195. 193|      * print an error message.
  196. 194|      */
  197. 195| 
  198. 196|     char  huge* *tabp;
  199. 197|     int          found;
  200. 198| 
  201. 199|     tabp = find_in_table( p, &found );
  202. 200| 
  203. 201|     if( found )
  204. 202|     {
  205. 203|         fprintf(stderr, "Malloc returned the same pointer twice!\n");
  206. 204|         exit( 1 );
  207. 205|     }
  208. 206| 
  209. 207|     if( Nel >= MAXPTR )
  210. 208|     {
  211. 209|         fprintf(stderr,
  212. 210|                 "Internal error [dmalloc()] too many pointers!\n");
  213. 211|         exit( 1 );
  214. 212|     }
  215. 213| 
  216. 214|     if( tabp == &Pointers[Nel] )
  217. 215|         Pointers[Nel++] = p;
  218. 216|     else
  219. 217|     {
  220. 218|         ++Nel;
  221. 219|         memmove( tabp+1, tabp,
  222. 220|                   (Nel - (tabp-Pointers)) * sizeof(*Pointers) );
  223. 221|         *tabp = p;
  224. 222|     }
  225. 223| }
  226. 224| 
  227. 225| /*------------------------------------------------------------*/
  228. 226| 
  229. 227| static  int     remove_from_table(p)
  230. 228| char    huge *p;
  231. 229| {
  232. 230|     /* Remove p from the pointers table, return 0 if it's not
  233. 231|      * there, 1 otherwise.
  234. 232|      */
  235. 233| 
  236. 234|     char  huge* *tabp;
  237. 235|     int          found;
  238. 236| 
  239. 237|     tabp = find_in_table( p, &found );
  240. 238| 
  241. 239|     if( !found )
  242. 240|         return 0;
  243. 241| 
  244. 242|     --Nel;
  245. 243|     memmove( tabp, tabp+1, 
  246. 244|                 (Nel - (tabp-Pointers)) * sizeof(*Pointers) );
  247. 245|     return 1;
  248. 246| }
  249. 247| 
  250. 248| /*------------------------------------------------------------*/
  251. 249| 
  252. 250| #ifdef MAIN
  253. 251| main()
  254. 252| {
  255. 253|     void        *p1, *p2, *p3, *p4, *p5;
  256. 254|     int         i;
  257. 255| 
  258. 256|     malloc_checking( 1 );
  259. 257| 
  260. 258|     p1 = dmalloc( 32767 );       ptab();
  261. 259|     p2 = dmalloc( 32767 );       ptab();
  262. 260|     p3 = dmalloc( 32767 );       ptab();
  263. 261|     p4 = dmalloc( 32767 );       ptab();
  264. 262|     p5 = dmalloc( 32767 );       ptab();
  265. 263| 
  266. 264|     dfree( p1 );                 ptab();
  267. 265|     dfree( p2 );                 ptab();
  268. 266|     dfree( p3 );                 ptab();
  269. 267|     dfree( p4 );                 ptab();
  270. 268|     dfree( p5 );                 ptab();
  271. 269| }
  272. 270| 
  273. 271| /*------------------------------------------------------------*/
  274. 272| 
  275. 273| ptab()
  276. 274| {
  277. 275|     int i;
  278. 276|     printf("\tNel = %d\n", Nel );
  279. 277|     for( i = 0; i < Nel; ++i )
  280. 278|         printf("\tPointers[%d] = %p\n", i, Pointers[i] );
  281. 279| }
  282. 280| #endif
  283.