json icon indicating copy to clipboard operation
json copied to clipboard

Memory leak when exception is thrown in adl_serializer::to_json

Open mjerabek opened this issue 2 years ago • 1 comments

Description

Throwing an exception in serializer function after the output json object is already initialized results in a memory leak (detected with both ASan and valgrind):

void adl_serializer<Foo>::to_json(json& j, Foo const& f) {
    j["a"] = 42;
    throw std::runtime_error("error");
}

Reproduction steps

Reproducer here: https://godbolt.org/z/dvorMExWh

Expected vs. actual results

Expected: no memory leak

Minimal code example

No response

Error messages

No response

Compiler and operating system

linux, clang 15, gcc 12.2

Library version

3.11.2, godbolt trunk, 7f72eedc2d4fc196d389f5aa0b2659f70dabe278

Validation

mjerabek avatar Dec 14 '22 10:12 mjerabek

This is throwing inside the constructor. When the constructor doesn't complete without exception, then the destructor is not run, meaning that m_value.destroy(m_type); is not called. Cleaning up from this is going to be tricky.
https://isocpp.org/wiki/faq/exceptions#selfcleaning-members

Off the top of my head, the constructor code that calls out to the adl serializer could detect an exception and call m_value.destroy(m_type); manually before rethrowing.

gregmarr avatar Dec 14 '22 16:12 gregmarr

This can be solved by either using a base class or a member var to do the cleanup. I would prefer one of those solutions, since they solve the problem of leaking memory permanently.

The stl uses base classes for containers managing memory (https://github.com/gcc-mirror/gcc/blob/7c755fd9018821b79ddc32ee507897860510986c/libstdc%2B%2B-v3/include/bits/stl_vector.h#L423). If we use a base class, we do not need to change the variable names. It would be enough to move some code into this base class.

I will implement a solution using a base class in #3901.

/edit I went with the solution using a member var, since it requires less changes to the existing code and the resulting code is simpler to understand.

barcode avatar Dec 27 '22 21:12 barcode