Small memory leak when using C API

There seems to be a (small) memory leak in the C API that ASAN detects. This is annoying, because we run ASAN regularly and we’ve worked pretty hard to be leak-free.

Example code to reproduce:

#define FDB_API_VERSION 630
#include <foundationdb/fdb_c.h>
#include <thread>
#include <iostream>
#include <cstdlib>

void checkError(fdb_error_t err) {
    if (err != 0) {
        std::cerr << err << "\n";
        abort();
    }
}

int main() {
    checkError(fdb_select_api_version(FDB_API_VERSION));
    checkError(fdb_setup_network());

    auto thread = std::thread([]() { checkError(fdb_run_network()); });

    FDBDatabase* db = nullptr;
    checkError(fdb_create_database("/tmp/fdb.cluster", &db));

    fdb_database_destroy(db);
    checkError(fdb_stop_network());
    thread.join();
}

Compiled using clang++-12 -fsanitize=address -std=c++17 /tmp/a.cc -o /tmp/a -lfdb_c -ldl -lrt -lpthread on x86_64 Linux, using foundationdb-clients-6.3.22.

=================================================================
==9014==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x4972dd in malloc (/tmp/a+0x4972dd)
    #1 0x7f3dab9d1cb7 in fdb_transaction_set_option (/lib/libfdb_c.so+0x7b1cb7)
    #2 0x7f3dab7627f3 in fdb_transaction_set_option (/lib/libfdb_c.so+0x5427f3)
    #3 0x7f3dab762905 in fdb_transaction_set_option (/lib/libfdb_c.so+0x542905)
    #4 0x7f3dab762c29 in fdb_transaction_set_option (/lib/libfdb_c.so+0x542c29)
    #5 0x7f3dab742dac in fdb_transaction_set_option (/lib/libfdb_c.so+0x522dac)
    #6 0x7f3dab46959e in fdb_transaction_set_option (/lib/libfdb_c.so+0x24959e)
    #7 0x7f3dab641686 in fdb_transaction_set_option (/lib/libfdb_c.so+0x421686)
    #8 0x7f3dab6417ea in fdb_transaction_set_option (/lib/libfdb_c.so+0x4217ea)
    #9 0x7f3dab55b19f in fdb_transaction_set_option (/lib/libfdb_c.so+0x33b19f)
    #10 0x7f3dab741536 in fdb_transaction_set_option (/lib/libfdb_c.so+0x521536)
    #11 0x7f3dab3ed7a1 in fdb_transaction_set_option (/lib/libfdb_c.so+0x1cd7a1)
    #12 0x7f3dab639f3e in fdb_transaction_set_option (/lib/libfdb_c.so+0x419f3e)
    #13 0x7f3dab3c4536 in fdb_transaction_set_option (/lib/libfdb_c.so+0x1a4536)
    #14 0x7f3dab3993d8 in fdb_run_network (/lib/libfdb_c.so+0x1793d8)
    #15 0x4cb4e0 in main::$_0::operator()() const (/tmp/a+0x4cb4e0)
    #16 0x4cb4bc in void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) (/tmp/a+0x4cb4bc)
    #17 0x4cb44c in std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) (/tmp/a+0x4cb44c)
    #18 0x4cb424 in void std::thread::_Invoker<std::tuple<main::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (/tmp/a+0x4cb424)
    #19 0x4cb3f4 in std::thread::_Invoker<std::tuple<main::$_0> >::operator()() (/tmp/a+0x4cb3f4)
    #20 0x4cb378 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0> > >::_M_run() (/tmp/a+0x4cb378)
    #21 0x7f3dab0ac6b3  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xda6b3)

Objects leaked above:
0x60300004da10 (32 bytes)

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

I know it’s only 32 bytes, but, because I don’t seem to have good symbol names in libfdb_c.so, it’s difficult to exclude in LSAN_OPTIONS. (If I also create a transaction, the leak grows to 136 bytes.)

Any thoughts? Is this expected? Am I forgetting to call some cleanup function?

Thanks,
-Tudor.