Search code examples
c++v8embedded-v8

hello-world.cc sample seems to leak memory


Just beginning to try to embed V8 in a C++ project. Given the complexity of this library, I thought it would be less terrifying if I could use valgrind as an additional regression tester. Hopefully, regularly checking for a clean run from valgrind would help catch at least some kinds of errors before I went too far down a bad road.

Unfortunately, it seems like right out of the box the hello-world.cc sample leaks some kB of memory. Stripping things out of the example, even just creating and deleting an Isolate won't give me a clean run.

// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libplatform/libplatform.h"
#include "v8.h"

int main(int argc, char* argv[]) {
  // Initialize V8.
  v8::V8::InitializeICUDefaultLocation(argv[0]);
  v8::V8::InitializeExternalStartupData(argv[0]);

  std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
  v8::V8::InitializePlatform(platform.get());
  v8::V8::Initialize();

  // Create a new Isolate and make it the current one.
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator =
      v8::ArrayBuffer::Allocator::NewDefaultAllocator();
  v8::Isolate* isolate = v8::Isolate::New(create_params);

  // Dispose the isolate and tear down V8.
  isolate->Dispose();
  v8::V8::Dispose();
  v8::V8::ShutdownPlatform();
  delete create_params.array_buffer_allocator;
  return 0;
}

I see this has already been noted by others: https://groups.google.com/forum/#!topic/v8-users/8Jv0JoTAMk0

I guess my question is: is it worth trying to achieve no leakage with v8, or is it likely that the library is always just going to leave some bits and bytes flopping in the breeze, as is often the case with complex libraries? Or, if I (and the other folks) have done something wrong with the hello-world example, that would be useful to know.


Solution

  • V8 developer here. I'm pretty sure that V8 is LSan (LeakSanitizer) clean. We're not testing with Valgrind regularly any more (mostly because it's too slow).

    In a quick test with the v8_hello_world binary in Valgrind, I do see two leak reports. One of them looks intentional: it's explicitly ignored in LSan and "not really a leak" because the memory is intended to be shared across Isolates, so no one Isolate is allowed to free it on teardown. You could try to free it on process exit, but that wouldn't have tangible benefit, it would only appease sanitizers, and cost both engineering and CPU/execution effort to achieve that. I'm not entirely sure about the other report but I suspect it's related.

    Long story short:

    • Valgrind might well be lacking a (very short) allow-list for intentional "leaks" (real or misdetected for whatever reason)
    • V8 shouldn't leak memory; if it does, then that's a bug
    • we mostly care about long-running Isolates being leak free, and are slightly less concerned about a single process creating and destroying millions of Isolates being leak free. I do think that that should work as well, but realistically it's probably less urgent to fix if there turns out to be a small, fixed amount of leakage per isolate.

    this has already been noted by others: https://groups.google.com/forum/#!topic/v8-users/8Jv0JoTAMk0

    If I'm reading that thread correctly, it was explicitly concerned with memory consumption that someone was observing but which Valgrind did not report as a leak.