koute / bytehound

A memory profiler for Linux.
Other
4.49k stars 193 forks source link

Using bytehound with MEMORY_PROFILER_USE_SHADOW_STACK=1 does not destroy exception objects properly #119

Open radx64 opened 12 months ago

radx64 commented 12 months ago

Hi, Great tool! During some profiling I've encountered very interesting leak which targets exception handling.

Seems that bytehound stack fast unwind algorithm omits destructors in exception objects marking them as leaky.

bytehound version: 0.11.0

MEMORY_PROFILER_USE_SHADOW_STACK=1 is default setting

Small example with simple test program:

#include <stdexcept>
#include <iostream>

void preconfigure()
{
     throw std::runtime_error("some_random_exception");
}

void handle()
{
    try
    {
        preconfigure();
    }
    catch(const std::exception& e)
    {
        return;   
    }
}

int main(int argc, char** argv)
{
    for (int i=0; i<1000; ++i)
    {
        handle();
    }
    return 0;
}

build with g++ (ver 11.4.0) with no extra flags and run with bytehound.so lib

g++ main.cpp
LD_PRELOAD=./libbytehound.so ./a.out

leaks

running same binary (not recompiled) with:

MEMORY_PROFILER_USE_SHADOW_STACK=0 LD_PRELOAD=./libbytehound.so ./a.out

shows no leaks no_leaks

The only difference is using shadow stack configuration parameter.

When I've tested calling the destructor of exception seems that it is not even called when shadow stack is used (so this is a real leak, but somehow caused by bytehound itself)