Back to index

avfs  1.0.1
leak.c
Go to the documentation of this file.
00001 // (c) 1999 Erwin S. Andreasen <erwin@andreasen.org>
00002 // Homepage: http://www.andreasen.org/LeakTracer/
00003 
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <stdlib.h>
00007 
00008 #include "internal.h"
00009 
00010 static int
00011     new_count, // how many memory blocks do we have
00012     leaks_count, // amount of entries in the below array
00013     first_free_spot; // Where is the first free spot in the leaks array?
00014 
00015 static size_t new_size;  // total size
00016 
00017 typedef struct {
00018     void *addr;
00019     size_t size;
00020     void *ret[10];
00021 //    void *ret2; // Not necessary anymore
00022 } Leak;
00023     
00024 static Leak *leaks;
00025 
00026 static AV_LOCK_DECL(lock);
00027 
00028 static int x(void *p)
00029 {
00030     int i = (int) p;
00031 
00032 #ifdef __linux__
00033     if(!(i & 0x8000000))
00034         return 0;
00035     
00036     return 1;
00037 #else
00038     if(i == 0 || i < 0)
00039         return 0;
00040 #endif
00041 
00042 //    av_log(AVLOG_DEBUG, "p: 0x%08x", i);
00043     
00044     return 1;
00045 }
00046 
00047 static void* register_alloc (size_t size) {
00048     void *p = malloc(size);
00049 
00050     new_count++;
00051     new_size += size;
00052     
00053     if (!p) { // We should really throw some sort of exception or call the new_handler
00054         av_log(AVLOG_ERROR, "LeakTracer: out of memory");
00055         _exit (1);
00056     }
00057     
00058     for (;;) {
00059         int i;
00060         int new_leaks_count;
00061         for (i = first_free_spot; i < leaks_count; i++)
00062             if (leaks[i].addr == NULL) {
00063                 leaks[i].addr = p;
00064                 leaks[i].size = size;
00065 
00066                 do {
00067                     if(!x(leaks[i].ret[0] = __builtin_return_address(0))) break;
00068                     if(!x(leaks[i].ret[1] = __builtin_return_address(1))) break;
00069                     if(!x(leaks[i].ret[2] = __builtin_return_address(2))) break;
00070                     if(!x(leaks[i].ret[3] = __builtin_return_address(3))) break;
00071                     if(!x(leaks[i].ret[4] = __builtin_return_address(4))) break;
00072                     if(!x(leaks[i].ret[5] = __builtin_return_address(5))) break;
00073                     if(!x(leaks[i].ret[6] = __builtin_return_address(6))) break;
00074                     if(!x(leaks[i].ret[7] = __builtin_return_address(7))) break;
00075                     if(!x(leaks[i].ret[8] = __builtin_return_address(8))) break;
00076                     if(!x(leaks[i].ret[9] = __builtin_return_address(9))) break;
00077                 } while(0);
00078 
00079 //                leaks[i].ret2 = __builtin_return_address(2);
00080                 first_free_spot = i+1;
00081                 return p;
00082             }
00083         
00084         // Allocate a bigger array
00085         // Note that leaks_count starts out at 0.
00086         new_leaks_count = leaks_count == 0 ? 16 : leaks_count * 2;
00087         leaks = (Leak*)realloc(leaks, sizeof(*leaks) * new_leaks_count);
00088         if (!leaks) {
00089             av_log(AVLOG_ERROR, "LeakTracer: out of memory");
00090             _exit(1);
00091         }
00092         memset(leaks+leaks_count, 0, sizeof(*leaks) * (new_leaks_count-leaks_count));
00093         leaks_count = new_leaks_count;
00094     }
00095 }
00096 
00097 static void *register_realloc (void *p, size_t size)
00098  {
00099      void *p1;
00100      int i;
00101 
00102      p1 = realloc(p, size);
00103     for (i = 0; i < leaks_count; i++)
00104         if (leaks[i].addr == p) {
00105             leaks[i].addr = p1;
00106             new_size += size - leaks[i].size;
00107             leaks[i].size = size;
00108             return p1;
00109         }
00110     
00111     av_log(AVLOG_ERROR, "LeakTracer: realloc on an already deleted value");
00112     abort();
00113 }
00114 
00115 
00116 static void register_free (void *p) 
00117 {
00118     int i;
00119     if (p == NULL)
00120         return;
00121     
00122     new_count--;
00123     for (i = 0; i < leaks_count; i++)
00124         if (leaks[i].addr == p) {
00125             leaks[i].addr = NULL;
00126             new_size -= leaks[i].size;
00127             if (i < first_free_spot)
00128                 first_free_spot = i;
00129             free(p);
00130             return;
00131         }
00132 
00133     av_log(AVLOG_ERROR, "LeakTracer: free on an already deleted value");
00134     abort();
00135 }
00136 
00137 void *av_malloc(size_t size)
00138 {
00139     void *res;
00140 
00141     AV_LOCK(lock);
00142     res = register_alloc(size);
00143     AV_UNLOCK(lock);
00144 
00145     return res;
00146 }
00147 
00148 void *av_calloc(size_t size)
00149 {
00150     void *res;
00151     
00152     AV_LOCK(lock);
00153     res = register_alloc(size);
00154     memset(res, 0, size);
00155     AV_UNLOCK(lock);
00156 
00157     return res;
00158 }
00159 
00160 void *av_realloc(void *p, size_t size)
00161 {
00162     void *res;
00163 
00164     AV_LOCK(lock);
00165     if(p == NULL)
00166         res = register_alloc(size);
00167     else if(size == 0) {
00168         register_free(p);
00169         res =  NULL;
00170     }
00171     else
00172         res = register_realloc(p, size);
00173     AV_UNLOCK(lock);
00174 
00175     return res;
00176 }
00177 
00178 void av_free(void *p)
00179 {
00180     AV_LOCK(lock);
00181     register_free(p);
00182     AV_UNLOCK(lock);
00183 }
00184 
00185 
00186 void av_check_malloc()
00187  {
00188     const char *filename = "/tmp/leak.out";
00189     FILE *fp;
00190 
00191     av_log(AVLOG_DEBUG, "leak_count: %i (%i)", new_count, leaks_count);
00192     
00193     if (!(fp = fopen(filename, "w")))
00194         av_log(AVLOG_ERROR, "LeakTracer: Could not open %s: %s\n", filename,
00195                  strerror(errno));
00196     else {
00197         int i;
00198         int numunfreed = 0;
00199 
00200         AV_LOCK(lock);
00201 
00202         fprintf(fp, 
00203                 "set prompt\n"
00204                 "echo\n"
00205                 "set listsize 0\n"
00206                 "set height 0\n");
00207         fprintf(fp, "echo leak size: %6d\\n\n", new_size);
00208         for (i = 0; i <  leaks_count; i++)
00209 
00210             if (leaks[i].addr != NULL) {
00211                 int j;
00212                 
00213                 numunfreed ++;
00214                 fprintf(fp, "echo -------------------------------------------------------------------------\\n\n");
00215                 fprintf(fp, "echo addr: %8p size: %9ld\\n\n",
00216                         leaks[i].addr,  (long) leaks[i].size);
00217                 for(j = 0; j < 10; j++) {
00218                     if(!x(leaks[i].ret[j]))
00219                         break;
00220 
00221                     fprintf(fp, "l *0x%x\n", (int) leaks[i].ret[j]);
00222                 }
00223             }
00224         AV_UNLOCK(lock);
00225 
00226         fclose(fp);
00227         av_log(AVLOG_WARNING, "number of unfreed pointers: %i", numunfreed);
00228     }
00229 }
00230