Home > Net >  Finding and debugging a memory leak without Valgrind
Finding and debugging a memory leak without Valgrind

Time:08-19

We have a program, that using IPC waits until it receives a message. When the program receives a message, it process it, calls some stored procedures in a database and then returns an answer.

One of our clients noticed that every time we receive a message, the memory usage is increased in 20kb. This program is supposed to process more than a million messages a day, so I was tasked with fixing this leak.

The problem is that the program isn't a basic executable, but runs in a proprietary application server, and uses proprietary libraries for almost anything. Because of this, I can't run the program by itself, which makes it impossible to run programs like valgrind.

I created a simple function to read the current memory usage, and spammed it everywhere, but when I went to the code, it was just a function call.

Code to check memory usage.

void PrintMemory(char *msg) {
    PREPARELOG(PrintMemory);
    FILE *fp = fopen("/proc/self/statm", "r");
    if(fp == NULL) {
        LOG(FAI, "[PrintMemory] Cant open /proc/self/statm");
        return;
    }
    long rss;

    fscanf(fp, "%*lu %ld", &rss);
    fclose(fp);

    LOG(NOT, "[PrintMemory] [%-30s] [%ld]", msg, rss);
}

Where PREPARELOGis a macro that sets some variables for the LOG macro.

After checking the log I see this:

[...]
[PrintMemory] [Function 1 end                ] [32633].
[PrintMemory] [Function 2 init               ] [32637].
[...]

Looking at the code, I see this:

ret = Function1(param);
PrintMemory("Function 1 end");

if (ret == 0) {
    Function2(&param1, &param2, param3, param4);
}
int Function2(int *param1, int *param2, char *param3, struct name* param4) {
    PREPARELOG(Function2);
    PrintMemory("Function 2 init");
    [...]
}

Checked the assembly of it just in case and saw this:

    call    PrintMemory #Function 1 end
    .loc 1 282 0
    movl    -28(%rbp),            
  • Related