Back to index

avfs  1.0.1
Classes | Functions | Variables
leak.c File Reference
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "internal.h"

Go to the source code of this file.

Classes

struct  Leak

Functions

static AV_LOCK_DECL (lock)
static int x (void *p)
static void * register_alloc (size_t size)
static void * register_realloc (void *p, size_t size)
static void register_free (void *p)
void * av_malloc (size_t size)
void * av_calloc (size_t size)
void * av_realloc (void *p, size_t size)
void av_free (void *p)
void av_check_malloc ()

Variables

static int new_count
static int leaks_count
static int first_free_spot
static size_t new_size
static Leakleaks

Class Documentation

struct Leak

Definition at line 17 of file leak.c.

Class Members
void * addr
void * ret
size_t size

Function Documentation

void* av_calloc ( size_t  size)

Definition at line 148 of file leak.c.

{
    void *res;
    
    AV_LOCK(lock);
    res = register_alloc(size);
    memset(res, 0, size);
    AV_UNLOCK(lock);

    return res;
}

Here is the call graph for this function:

void av_check_malloc ( )

Definition at line 186 of file leak.c.

 {
    const char *filename = "/tmp/leak.out";
    FILE *fp;

    av_log(AVLOG_DEBUG, "leak_count: %i (%i)", new_count, leaks_count);
    
    if (!(fp = fopen(filename, "w")))
        av_log(AVLOG_ERROR, "LeakTracer: Could not open %s: %s\n", filename,
                 strerror(errno));
    else {
        int i;
        int numunfreed = 0;

        AV_LOCK(lock);

        fprintf(fp, 
                "set prompt\n"
                "echo\n"
                "set listsize 0\n"
                "set height 0\n");
        fprintf(fp, "echo leak size: %6d\\n\n", new_size);
        for (i = 0; i <  leaks_count; i++)

            if (leaks[i].addr != NULL) {
                int j;
                
                numunfreed ++;
                fprintf(fp, "echo -------------------------------------------------------------------------\\n\n");
                fprintf(fp, "echo addr: %8p size: %9ld\\n\n",
                        leaks[i].addr,  (long) leaks[i].size);
                for(j = 0; j < 10; j++) {
                    if(!x(leaks[i].ret[j]))
                        break;

                    fprintf(fp, "l *0x%x\n", (int) leaks[i].ret[j]);
                }
            }
        AV_UNLOCK(lock);

        fclose(fp);
        av_log(AVLOG_WARNING, "number of unfreed pointers: %i", numunfreed);
    }
}

Here is the call graph for this function:

void av_free ( void *  p)

Definition at line 178 of file leak.c.

{
    AV_LOCK(lock);
    register_free(p);
    AV_UNLOCK(lock);
}

Here is the call graph for this function:

static AV_LOCK_DECL ( lock  ) [static]
void* av_malloc ( size_t  size)

Definition at line 137 of file leak.c.

{
    void *res;

    AV_LOCK(lock);
    res = register_alloc(size);
    AV_UNLOCK(lock);

    return res;
}

Here is the call graph for this function:

void* av_realloc ( void *  p,
size_t  size 
)

Definition at line 160 of file leak.c.

{
    void *res;

    AV_LOCK(lock);
    if(p == NULL)
        res = register_alloc(size);
    else if(size == 0) {
        register_free(p);
        res =  NULL;
    }
    else
        res = register_realloc(p, size);
    AV_UNLOCK(lock);

    return res;
}

Here is the call graph for this function:

static void* register_alloc ( size_t  size) [static]

Definition at line 47 of file leak.c.

                                          {
    void *p = malloc(size);

    new_count++;
    new_size += size;
    
    if (!p) { // We should really throw some sort of exception or call the new_handler
        av_log(AVLOG_ERROR, "LeakTracer: out of memory");
        _exit (1);
    }
    
    for (;;) {
        int i;
        int new_leaks_count;
        for (i = first_free_spot; i < leaks_count; i++)
            if (leaks[i].addr == NULL) {
                leaks[i].addr = p;
                leaks[i].size = size;

                do {
                    if(!x(leaks[i].ret[0] = __builtin_return_address(0))) break;
                    if(!x(leaks[i].ret[1] = __builtin_return_address(1))) break;
                    if(!x(leaks[i].ret[2] = __builtin_return_address(2))) break;
                    if(!x(leaks[i].ret[3] = __builtin_return_address(3))) break;
                    if(!x(leaks[i].ret[4] = __builtin_return_address(4))) break;
                    if(!x(leaks[i].ret[5] = __builtin_return_address(5))) break;
                    if(!x(leaks[i].ret[6] = __builtin_return_address(6))) break;
                    if(!x(leaks[i].ret[7] = __builtin_return_address(7))) break;
                    if(!x(leaks[i].ret[8] = __builtin_return_address(8))) break;
                    if(!x(leaks[i].ret[9] = __builtin_return_address(9))) break;
                } while(0);

//                leaks[i].ret2 = __builtin_return_address(2);
                first_free_spot = i+1;
                return p;
            }
        
        // Allocate a bigger array
        // Note that leaks_count starts out at 0.
        new_leaks_count = leaks_count == 0 ? 16 : leaks_count * 2;
        leaks = (Leak*)realloc(leaks, sizeof(*leaks) * new_leaks_count);
        if (!leaks) {
            av_log(AVLOG_ERROR, "LeakTracer: out of memory");
            _exit(1);
        }
        memset(leaks+leaks_count, 0, sizeof(*leaks) * (new_leaks_count-leaks_count));
        leaks_count = new_leaks_count;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void register_free ( void *  p) [static]

Definition at line 116 of file leak.c.

{
    int i;
    if (p == NULL)
        return;
    
    new_count--;
    for (i = 0; i < leaks_count; i++)
        if (leaks[i].addr == p) {
            leaks[i].addr = NULL;
            new_size -= leaks[i].size;
            if (i < first_free_spot)
                first_free_spot = i;
            free(p);
            return;
        }

    av_log(AVLOG_ERROR, "LeakTracer: free on an already deleted value");
    abort();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* register_realloc ( void *  p,
size_t  size 
) [static]

Definition at line 97 of file leak.c.

 {
     void *p1;
     int i;

     p1 = realloc(p, size);
    for (i = 0; i < leaks_count; i++)
        if (leaks[i].addr == p) {
            leaks[i].addr = p1;
            new_size += size - leaks[i].size;
            leaks[i].size = size;
            return p1;
        }
    
    av_log(AVLOG_ERROR, "LeakTracer: realloc on an already deleted value");
    abort();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int x ( void *  p) [static]

Definition at line 28 of file leak.c.

{
    int i = (int) p;

#ifdef __linux__
    if(!(i & 0x8000000))
        return 0;
    
    return 1;
#else
    if(i == 0 || i < 0)
        return 0;
#endif

//    av_log(AVLOG_DEBUG, "p: 0x%08x", i);
    
    return 1;
}

Here is the caller graph for this function:


Variable Documentation

int first_free_spot [static]

Definition at line 11 of file leak.c.

Leak* leaks [static]

Definition at line 24 of file leak.c.

int leaks_count [static]

Definition at line 11 of file leak.c.

int new_count [static]

Definition at line 11 of file leak.c.

size_t new_size [static]

Definition at line 15 of file leak.c.