source: git/Singular/mmcheck.c @ fdc537

spielwiese
Last change on this file since fdc537 was 3b8058, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* fixed mmcheck git-svn-id: file:///usr/local/Singular/svn/trunk@3902 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mmcheck.c,v 1.19 1999-11-23 19:35:14 obachman Exp $ */
5
6/*
7* ABSTRACT: several checking routines to help debugging the memory subsystem
8*/
9
10#define _POSIX_SOURCE 1
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include "mod2.h"
16
17#ifdef MDEBUG
18
19#include "mmemory.h"
20#include "mmprivate.h"
21#include "mmpage.h"
22#ifdef MTRACK
23#include "mmbt.h"
24#endif
25
26DBMCB mm_theDBused;
27DBMCB mm_theDBfree;
28
29void * mm_maxAddr = NULL;
30void * mm_minAddr = NULL;
31
32/* int mm_MDEBUG = MDEBUG; */
33int mm_MDEBUG = 0;
34
35int mm_markCurrentUsage = 0;
36int mm_referenceWatch = 0;
37
38/**********************************************************************
39 *
40 * Auxillary routines
41 *
42 **********************************************************************/
43
44void mmMoveDBMCB ( pDBMCB from, pDBMCB to, DBMCB * what )
45{
46  what->prev->next = what->next;
47  if ( what->next != NULL )
48    what->next->prev = what->prev;
49  what->prev = to;
50  what->next = to->next;
51  if (to->next!=NULL)
52    to->next->prev=what;
53  to->next = what;
54}
55
56void mmMoveDBMCBInto ( pDBMCB to, pDBMCB what )
57{
58  if (to->next !=NULL)
59  {
60    what->next = to->next;
61    what->next->prev = what;
62  }
63  to->next = what;
64  what->prev = to;
65}
66
67void mmTakeOutDBMCB ( pDBMCB what )
68{
69  what->prev->next = what->next;
70  if ( what->next != NULL )
71    what->next->prev = what->prev;
72}
73
74#ifndef HAVE_AUTOMATIC_GC
75void mmDBSetHeapsOfBlocks(memHeap fromheap, memHeap toheap)
76{
77
78  memHeapPage pages = fromheap->pages;
79  int nblocks = SIZE_OF_HEAP_PAGE / toheap->size;
80  int i;
81
82  assume(fromheap->size == toheap->size);
83  while (pages != NULL)
84  {
85    DBMCB *what = (DBMCB*) (((char*) pages) + SIZE_OF_HEAP_PAGE_HEADER);
86
87    for (i=0; i<nblocks; i++)
88    {
89      what->heap = toheap;
90      what = (DBMCB*) (((char*) what)  + toheap->size);
91    }
92    pages = pages->next;
93  }
94}
95#endif
96
97void mmDBInitNewHeapPage(memHeap heap, memHeapPage page)
98{
99#ifndef HAVE_AUTOMATIC_GC
100  DBMCB* what = (DBMCB*) heap->current;
101#else
102  DBMCB* what =  (DBMCB*) page->current;
103#endif
104 
105  DBMCB* prev = NULL;
106  size_t size = SizeFromRealSize(heap->size);
107
108  if (mm_minAddr == 0 || mm_minAddr > (void*) what)
109    mm_minAddr = (void*) what;
110
111  while (what != NULL)
112  {
113    memset(&(what->next), 0, sizeof(DBMCB) - sizeof(void*));
114    mmFillDBMCB(what, size, heap, MM_FREEFLAG, __FILE__, __LINE__);
115    mmMoveDBMCBInto(&mm_theDBfree, what);
116    prev = what;
117    what = *((void**) what);
118  }
119
120  if (mm_maxAddr == 0 || mm_maxAddr < (void*) prev)
121    mm_maxAddr = (void*) prev;
122}
123
124static int mmPrintDBMCB ( DBMCB * what, char* msg , int given_size)
125{
126  (void)fprintf( stderr, "warning: %s\n", msg );
127  (void)fprintf( stderr, "block %p allocated in: %s:%d ",
128                 &(what->data),
129                 what->allocated_fname, what->freed_lineno );
130#ifdef MTRACK
131  mmDBPrintThisStack(stderr, what, MM_PRINT_ALL_STACK, 0);
132#endif
133
134  if ((what->flags & MM_FREEFLAG) && what->freed_fname != NULL)
135  {
136    (void)fprintf( stderr, "freed in: %s:%d ",
137                   what->freed_fname, what->freed_lineno );
138#ifdef MTRACK_FREE
139    mmDBPrintThisStack(stderr, what, MM_PRINT_ALL_STACK, 1);
140#endif
141  }
142#ifndef MTRACK
143  fprintf(stderr, "\n");
144#endif
145
146  if (strcmp(msg,"size")==0)
147    (void)fprintf( stderr, "size is: %d, but check said %d \n",
148      (int)what->size, given_size );
149  else
150    (void)fprintf( stderr, "size is: %d\n", (int)what->size );
151  return 0;
152}
153
154void mmPrintUsedList( )
155{
156  DBMCB * what;
157  what=mm_theDBused.next;
158  fprintf(stderr,"list of used blocks:\n");
159  while (what!=NULL)
160  {
161    (void)fprintf( stderr, "%d bytes at %p in: %s:%d\n",
162      (int)what->size, what, what->allocated_fname, what->allocated_lineno);
163    what=what->next;
164  }
165}
166
167void mmPrintFL( const char* fname, const int lineno )
168{
169  (void)fprintf( stderr, "occured in %s:%d\n", fname, lineno );
170}
171
172/**********************************************************************
173 *
174 * Init routines
175 *
176 **********************************************************************/
177
178#define MM_USED_PATTERN 255
179#define MM_FREE_PATTERN 251
180#define MM_FRONT_PATTERN 247
181#define MM_BACK_PATTERN  249
182
183void mmFillDBMCB(DBMCB* what, size_t size, memHeap heap,
184                 int flags, char* fname, int lineno)
185{
186  void* addr = &(what->data);
187
188  what->heap = heap;
189  what->size = size;
190  if ((what->flags & MM_USEDFLAG) && (flags && MM_FREEFLAG))
191  {
192    what->freed_fname = fname;
193    what->freed_lineno = lineno;
194  }
195  else
196  {
197    what->allocated_fname = fname;
198    what->allocated_lineno = lineno;
199  }
200
201  if (flags == MM_FREEFLAG)
202  {
203    what->flags &= ~ MM_USEDFLAG;
204    what->flags |= MM_FREEFLAG;
205    what->flags &= ~ MM_CURRENTLY_USEDFLAG;
206  }
207  else if (flags == MM_USEDFLAG)
208  {
209    what->flags &= ~ MM_FREEFLAG;
210    what->flags |= MM_USEDFLAG;
211    if (mm_markCurrentUsage == 1)
212      what->flags |= MM_CURRENTLY_USEDFLAG;
213  }
214
215  if (flags & MM_FREEFLAG)
216    memset(addr, MM_FREE_PATTERN, size);
217
218  memset(what->front_pattern, MM_FRONT_PATTERN, MM_NUMBER_OF_FRONT_PATTERNS);
219  memset(addr, 255, size);
220  memset((char*) addr + size, MM_BACK_PATTERN, DebugOffsetBack);
221}
222
223void mmMarkInitDBMCB()
224{
225  DBMCB * what=mm_theDBused.next;
226  while (what != NULL)
227  {
228    what->flags |= MM_INITFLAG;
229    what = what->next;
230  }
231}
232
233/**********************************************************************
234 *
235 * Check routines
236 *
237 **********************************************************************/
238
239static int mmCheckPattern(char* ptr, char pattern, size_t size)
240{
241  int i;
242
243  for (i = 0; i<size; i++)
244    if (ptr[i] != pattern) return 0;
245  return 1;
246}
247
248#ifdef unix
249#ifdef sun
250extern int end;
251#define _end end
252#else
253extern int _end;
254#endif
255#endif
256static int mmCheckSingleDBMCB ( DBMCB * what, int size , int flags)
257{
258  char * patptr;
259  int i;
260  int ok=1;
261  if ( ((long)what % 4 ) != 0 )
262  {
263    fprintf( stderr, "warning: odd address\n" );
264    assume(0);
265    return 0;
266  }
267  if ( (void*)what > mm_maxAddr && mm_maxAddr != NULL)
268  {
269    fprintf( stderr, "warning: address too high\n" );
270    assume(0);
271    return 0;
272  }
273  if ( (void*)what < mm_minAddr && mm_minAddr != NULL)
274  {
275    fprintf( stderr, "warning: address too low\n" );
276    assume(0);
277    return 0;
278  }
279  if (! mmIsNotAddrOnFreePage(what))
280  {
281    fprintf(stderr, "warning: address on freed page\n");
282    assume(0);
283    return 0;
284  }
285
286  if ( ((long)what->allocated_fname<1000)
287  #ifdef unix
288       ||((long)what->allocated_fname>(long)&(_end))
289  #endif
290  )
291  { /* fname should be in the text segment */
292    fprintf(stderr, "warning: allocated_fname (%lx) out of range\n", (long)what->allocated_fname );
293    assume(0);
294    what->allocated_fname="???";
295    ok=0;
296  }
297  if ( (what->allocated_lineno< -9999) ||(what->allocated_lineno>9999) )
298  {
299    fprintf( stderr, "warning: allocated_lineno %d out of range\n",what->allocated_lineno );
300    assume(0);
301    what->allocated_lineno=0;
302    ok=0;
303  }
304
305  if ((what->flags & MM_FREEFLAG) && what->freed_fname != NULL)
306  {
307    if ( ((long)what->freed_fname<1000)
308#ifdef unix
309         ||((long)what->freed_fname>(long)&(_end))
310#endif
311         )
312    { /* fname should be in the text segment */
313      fprintf(stderr, "warning: freed_fname (%lx) out of range\n", (long)what->freed_fname );
314      assume(0);
315      what->freed_fname="???";
316      ok=0;
317    }
318    if ( (what->freed_lineno< -9999) ||(what->freed_lineno>9999) )
319    {
320      fprintf( stderr, "warning: freed_lineno %d out of range\n",what->freed_lineno );
321      assume(0);
322      what->freed_lineno=0;
323      ok=0;
324    }
325  }
326
327
328  #ifdef unix
329  if ( (what->next!=NULL)
330       && (((long)what->next>(long)mm_maxAddr)
331           || ((long)what->next<(long)mm_minAddr) )
332       && (((long)what->next>(long)&_end)
333           || ((long)what->next<1000))
334  )
335  {
336    fprintf( stderr, "warning: next (%lx) out of range\n", (long)what->next );
337    assume(0);
338    what->next=NULL;
339    ok=0;
340  }
341  if ( (what->prev!=NULL)
342       && (((long)what->prev>(long)mm_maxAddr)
343           || ((long)what->prev<(long)mm_minAddr) )
344       && (((long)what->prev>(long)&_end)
345           || ((long)what->prev<1000)))
346  {
347    fprintf( stderr, "warning: prev (%lx) out of range\n", (long)what->prev );
348    assume(0);
349    what->prev=NULL;
350    ok=0;
351  }
352  #endif
353
354  if ( ( what->flags & flags ) != flags )
355  {
356    if (flags & MM_USEDFLAG)
357    {
358      mmMoveDBMCB(&mm_theDBfree, &mm_theDBused, what);
359      what->flags |= MM_USEDFLAG;
360      return mmPrintDBMCB( what, "block has been freed but still in use", 0 );
361    }
362    return mmPrintDBMCB(what, "block still in use but should be free", 0);
363  }
364
365  if (mm_referenceWatch)
366  {
367    if (what->flags & MM_REFERENCEFLAG)
368    {
369//      mm_referenceWatch = 0;
370      return mmPrintDBMCB(what, "reference", 0);
371    }
372    else
373      what->flags |= MM_REFERENCEFLAG;
374  }
375
376  if ( what->size != size )
377    return mmPrintDBMCB( what, "size", size );
378
379  i = mmGetIndex(size);
380
381  if (! mmCheckPattern(what->front_pattern, MM_FRONT_PATTERN,
382                       MM_NUMBER_OF_FRONT_PATTERNS))
383    return mmPrintDBMCB(what , "front pattern", 0);
384  if ((what->flags & MM_FREEFLAG)  &&
385      ! mmCheckPattern((char*)&(what->data), MM_FREE_PATTERN, 0))
386    return mmPrintDBMCB(what, "free pattern", 0);
387  if (! mmCheckPattern((char*) &(what->data) + size,
388                       MM_BACK_PATTERN, DebugOffsetBack))
389    return mmPrintDBMCB(what, "back pattern", 0);
390
391  if ( ( what->next != NULL ) && ( what->next->prev != what ) )
392  {
393    mmPrintDBMCB( what->next, "next", 0 );
394    what->next->prev=what;
395    return mmPrintDBMCB( what, "chain:n", 0 );
396  }
397  if ( ( what->prev != NULL ) && ( what->prev->next != what ) )
398  {
399    mmPrintDBMCB( what->prev, "prev", 0 );
400    what->prev->next=what;
401    return mmPrintDBMCB( what, "chain:p", 0 );
402  }
403  if(ok==0)
404  {
405    return mmPrintDBMCB( what, "see above", 0 );
406  }
407  if (mm_markCurrentUsage == 1)
408  {
409    what->flags |= MM_CURRENTLY_USEDFLAG;
410  }
411  return 1;
412}
413
414static int mmCheckDBMCBList(DBMCB * list, int flags)
415{
416  assume(flags == MM_FREEFLAG || flags == MM_USEDFLAG);
417
418  if (mmGListHasCycle(list,
419                      (void*) &(mm_theDBfree.next) -
420                      (void*) &(mm_theDBfree)))
421  {
422    fprintf(stderr, "%s list contains cycles\n",
423            (flags == MM_FREEFLAG ? "Free" : "Used"));
424    assume(0);
425    return 0;
426  }
427
428  while (list != NULL)
429  {
430    if (! mmCheckSingleDBMCB(list, list->size, flags))
431    {
432      fprintf(stderr, "while check of %s list\n",
433            (flags == MM_FREEFLAG ? "free" : "used"));
434      return 0;
435    }
436    list = list->next;
437  }
438
439  return 1;
440}
441
442int mmTestMemory()
443{
444  if (mmCheckDBMCBList(mm_theDBused.next, MM_USEDFLAG))
445    return mmCheckDBMCBList(mm_theDBfree.next, MM_FREEFLAG);
446  return 0;
447}
448
449
450static int   mmIsAddrOnDList(DBMCB *what, DBMCB* list, int s)
451{
452  while (list != NULL)
453  {
454    if (list == what) return 1;
455    list = list->next;
456  }
457  return 0;
458}
459
460static int mmCheckListContainment(DBMCB * what, int flags)
461{
462  if ( mmIsAddrOnDList((void*) what, mm_theDBused.next,
463                       (void*) &(mm_theDBused.next) -
464                       (void*) &(mm_theDBused)))
465  {
466    if (flags == MM_FREEFLAG)
467      return mmPrintDBMCB(what, "Free flag and in used list", 0);
468  }
469  else
470  {
471    if (flags == MM_USEDFLAG)
472      return mmPrintDBMCB(what, "Used flag but not in used list", 0);
473  }
474
475  if ( mmIsAddrOnDList((void*) what, mm_theDBfree.next,
476                       (void*) &(mm_theDBfree.next) -
477                       (void*) &(mm_theDBfree)))
478  {
479    if (flags == MM_USEDFLAG)
480      return mmPrintDBMCB(what, "Used flag and in free list", 0);
481  }
482  else
483  {
484    if (flags == MM_FREEFLAG)
485      return mmPrintDBMCB(what,"Free flag but not in free list", 0);
486  }
487  return 1;
488}
489
490int mmCheckDBMCB ( DBMCB * what, int size , int flags)
491{
492
493  assume(flags == MM_FREEFLAG || flags == MM_USEDFLAG);
494  if (! mmCheckSingleDBMCB(what, size, flags))
495    return 0;
496
497  if (mm_MDEBUG > 1 && ! mmTestMemory()) return 0;
498
499  if (mm_MDEBUG > 0 && ! mmCheckListContainment(what, flags)) return 0;
500
501  return 1;
502}
503
504/**********************************************************************
505 *
506 * Test routines
507 *
508 **********************************************************************/
509static BOOLEAN mmDBTestHeapBlockS(const void* adr, const memHeap heap,
510                                  const size_t size,
511                                  const char * fname, const int lineno )
512{
513  DBMCB * what;
514
515  if ( adr == NULL || size == 0)
516    return TRUE;
517
518  if (mm_MDEBUG > 2 && ! mmTestHeaps())
519  {
520    mmPrintFL( fname, lineno );
521    return FALSE;
522  }
523
524  what = (DBMCB*)((char*)(adr) - DebugOffsetFront);
525
526  if ( ! mmCheckDBMCB( what, size, MM_USEDFLAG) )
527  {
528    mmPrintFL( fname, lineno );
529    return FALSE;
530  }
531
532  if (what->heap != heap)
533  {
534    mmPrintDBMCB(what, "Not from specified heap", 0);
535    mmPrintFL( fname, lineno );
536    return FALSE;
537  }
538
539#ifdef HEAP_DEBUG
540  return
541    mmDebugCheckHeapAddr(what, heap, MM_HEAP_ADDR_USED_FLAG, fname, lineno);
542#else
543  return TRUE;
544#endif
545}
546
547BOOLEAN mmDBTestHeapBlock(const void* adr, const memHeap heap,
548                          const char * fname, const int lineno )
549{
550  return mmDBTestHeapBlockS(adr, heap,
551                            SizeFromRealSize(heap->size),
552                            fname, lineno);
553}
554
555BOOLEAN mmDBTestBlock(const void* adr, const size_t size,
556                      const char * fname, const int lineno)
557{
558  int i;
559  DBMCB * what;
560
561  if ( ( adr == NULL ) || ( size == 0 ) ) return TRUE;
562
563  i = mmGetIndex(size);
564  if (i < 0)
565  {
566    what = (DBMCB*)((char*)(adr) - DebugOffsetFront);
567    if ( ! mmCheckDBMCB( what, size, MM_USEDFLAG) )
568    {
569      mmPrintFL( fname, lineno );
570      return FALSE;
571    }
572    return TRUE;
573  }
574  else
575  {
576    return mmDBTestHeapBlockS(adr, &(mm_theList[i]), size, fname, lineno);
577  }
578}
579
580
581BOOLEAN mmDBTest( const void* adr, const char * fname, const int lineno )
582{
583  if (adr!=NULL)
584  {
585    size_t l;
586    adr = (size_t*)adr-1;
587#ifdef ALIGN_8
588    l= (adr<=mm_maxAddr) ? (*(size_t*)((long)adr&(~((long)7)))) :0;
589#else
590    l= (adr<=mm_maxAddr) ? (*(size_t*)((long)adr&(~((long)3)))) :0;
591#endif
592    return mmDBTestBlock( adr,l, fname, lineno );
593  }
594  return TRUE;
595}
596
597/**********************************************************************
598 *
599 * Routines fro marking
600 *
601 **********************************************************************/
602void mmMarkCurrentUsageState()
603{
604  DBMCB* what = mm_theDBused.next;
605  mm_markCurrentUsage = -1;
606  while (what != NULL)
607  {
608    what->flags |= MM_CURRENTLY_USEDFLAG;
609    what = what->next;
610  }
611}
612
613void mmMarkCurrentUsageStart()
614{
615  mm_markCurrentUsage = 1;
616}
617
618void mmMarkCurrentUsageStop()
619{
620  mm_markCurrentUsage = 0;
621}
622
623void mmPrintUnMarkedBlocks()
624{
625  DBMCB* what = mm_theDBused.next;
626  int found = 0;
627  while (what != NULL)
628  {
629    if (! (what->flags & MM_CURRENTLY_USEDFLAG))
630    {
631      mmPrintDBMCB(what, "unused", 0);
632      what->flags |= MM_CURRENTLY_USEDFLAG;
633      found = 1;
634    }
635    what = what->next;
636  }
637  if (found) fprintf(stderr, "\nFinished found\n");
638}
639
640void mmStartReferenceWatch()
641{
642  DBMCB* what = mm_theDBused.next;
643  mm_referenceWatch = 1;
644  while (what != NULL)
645  {
646    what->flags &= ~ MM_REFERENCEFLAG;
647    what = what->next;
648  }
649}
650
651void mmStopReferenceWatch()
652{
653  mm_referenceWatch = 0;
654}
655
656#endif /* MDEBUG */
657
658
659
Note: See TracBrowser for help on using the repository browser.