简体   繁体   中英

Is there anyway to check if there is memory leaks in C?

i recently learnt about memalloc() and free() and i was just wondering if there was a way to appropriately check if all the memallocs are appropriately being freed?

I have this code right here for an implementation of doubly linked list, and im unclear whether id need to go through every node and deallocate each p1 and p2, or does doing it once count?:

struct s {
    int data;
    struct s *p1;
    struct s *p2;
};

void freedl(struct s *p)
{
    if(p->p1 != NULL)
    {
        printf("free %d \n", p->p1->data);
    }

    if(p->p2 != NULL)
    {
        freedl(p->p2);
    }
    else
    {
        printf("free last %d", p->data);
        free(p);
    }

}

int main(void) {

    struct s *one, *two, *three, *four, *five, *six;

    one = malloc(sizeof *one);
    two = malloc(sizeof *two);
    three = malloc(sizeof *three);
    four = malloc(sizeof *four);
    five = malloc(sizeof *five);
    six = malloc(sizeof *six);

    one->data = 1;
    one->p1 = NULL;
    one->p2 = two;

    two->data = 2;
    two->p1 = one;
    two->p2 = three;

    three->data = 3;
    three->p1 = two;
    three->p2 = four;

    four->data = 4;
    four->p1 = three;
    four->p2 = five;

    five->data = 5;
    five->p1 = four;
    five->p2 = six;

    six->data = 6;
    six->p1 = five;
    six->p2 = NULL;

    freedl(one);

    return EXIT_SUCCESS;
}

and I'd just like to make sure I'm doing it right!

The answer is "yes"; exactly how hard it is depends on what OS you're in.

If you're in Linux, Mac OS X or one of the BSDs (FreeBSD, OpenBSD, ...):

(and possibly Haiku)

You can use an utility called valgrind . It is an excellent utility, designed for (among other things) exactly that --- checking for memory leaks.

The basic usage is simple:

valgrind ./my-program

It is a complex utility though, so I'd recommend checking out the valgrind manual for more advanced usage.

It actually does a far more than that, in that it can detect many (but not all) out-of-bounds accesses and similar problems. It also includes other tools that may come useful, such as callgrind for profiling code.

Do note, however, that valgrind will make your program run very slowly, due to the way it operates.

Any other OS (incl. Windows):

Unfortunately, there is no such utility for Windows (no free ones, anyways; and the commercial ones costed a small fortune, last I've checked --- and none does quite as much as valgrind & friends can).

What you can do, however, is implement macros and check manually on exit:

#define malloc(size) chk_malloc(size, __FILE__, __LINE__)
#define free(ptr)    chk_free(ptr, __FILE__, __LINE__)
// etc... for realloc, calloc

...

// at start of main():
atexit(chk_report); // report problems when program exits normally

You then have to implement chk_malloc , chk_free and so on. There can be some "leaks", however, if you do things such as setAllocator(malloc) . If you're okay with losing line information, you can then try doing:

#define malloc chk_malloc // chk_malloc now only takes 1 argument
#define free   chk_free
...

There are certain hacks which would allow you to keep file/line info even with this #define , but they would seriously complicate matters (it would involve basically hacking closures into C).

If you don't want to change the code in any way, you could try your luck with replacing just those functions (by replacing the stdlib with your own shim DLL), though you won't get file/line information that way. It might also be problematic if the compilation was done statically, or if the compiler has replaced it with some intrinsic (which is unlikely for malloc , but not inconceivable).

The implementation can be very simple, or it can be complex, it's up to you. I don't know of any existing implementations, but you can probably find something online.

System allocators have some way of getting statistics (such as bytes allocated) out of them. ( mallinfo on linux). At the beginning of your program you should store the number of bytes allocated and at the end you need t make sure the number is the same. If the number is different, you have a potential memory leak.

Finding that leak is another story. Tools like valgrind will help.

You can valgrind but it can be a little bit slow Or something buildin in compiler. For example in clang (I think that in gcc 4.9 too) there are LeakSanitizer :

$ cat example.c
int main()
{
    malloc(100);
    return 0;
}

$ clang -fsanitize=leak -g example.c -fsanitize=address
$ ASAN_OPTIONS=detect_leaks=1  ./a.out

=================================================================
==9038==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 100 byte(s) in 1 object(s) allocated from:
    #0 0x46c871 (/home/debian/a.out+0x46c871)
    #1 0x49888c (/home/debian/a.out+0x49888c)
    #2 0x7fea542e4ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)

SUMMARY: AddressSanitizer: 100 byte(s) leaked in 1 allocation(s).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM