title: V8 memory leaks and conditional jumps
body: <p>I have embedded V8 in my C application. I am able to execute javascript in my C application. However I see bunch of memory leaks, conditional jumps when I tried to run my C application. I have total 4 files.</p>
  
  <h2>1. mjse_int.h</h2>
  
  <pre><code>typedef struct
  {
      std::unique_ptr&lt;v8::Platform&gt; platform;
      v8::Isolate::CreateParams create_params;
      v8::Isolate *isolate;
  }MJSEInstance;
  </code></pre>
  
  <h2>2. mjse.h</h2>
  
  <pre><code>#ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
  * @brief Create MJSE instance
  */
  void *mjse_create_instance(char **argv);
  
  /**
  * @brief Destroy MJSE instance
  * @param instance -&gt; MJSE instance
  */
  void mjse_destroy_instance(void *minstance);
  
  /**
  * @brief Executes a script
  * @param minstance - MJSE instance
  * @param script - the javascript
  * @param scriptlen - Length of script
  */
  void mjse_execute_script(void *minstance, char *script, int scriptlen);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  </code></pre>
  
  <h2>3. mjse.c</h2>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include "include/libplatform/libplatform.h"
  #include "include/v8.h"
  #include "mjse.h"
  #include "mjse_int.h"
  
  extern "C"  {
  
  using namespace v8;
  
  void *mjse_create_instance(char **argv)
  {
      MJSEInstance *instance = (MJSEInstance *)calloc(1, sizeof(MJSEInstance));
  
      v8::V8::InitializeICUDefaultLocation(argv[0]);
      v8::V8::InitializeExternalStartupData(argv[0]);
      instance-&gt;platform = v8::platform::NewDefaultPlatform();
  
      v8::V8::InitializePlatform(instance-&gt;platform.get());
      v8::V8::Initialize();
  
      instance-&gt;create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
      instance-&gt;isolate = v8::Isolate::New(instance-&gt;create_params);
  
      printf("Version: %s\n", v8::V8::GetVersion());
  
      return instance;
  }
  
  void mjse_destroy_instance(void *minstance)
  {
      MJSEInstance *instance = (MJSEInstance *)minstance;
  
      if(instance == NULL)
          return;
  
      if(instance-&gt;isolate)
      {
          instance-&gt;isolate-&gt;Dispose();
      }
  
      v8::V8::Dispose();
      v8::V8::ShutdownPlatform();
  
      if(instance-&gt;create_params.array_buffer_allocator)
      {
          delete instance-&gt;create_params.array_buffer_allocator;
      }
  
      free(instance);
  }
  
  void mjse_execute_script(void *minstance, char *script, int scriptlen)
  {
      MJSEInstance *instance = (MJSEInstance *)minstance;
  
      v8::Isolate::Scope isolate_scope(instance-&gt;isolate);
  
      // Create a stack-allocated handle scope.
      v8::HandleScope handle_scope(instance-&gt;isolate);
  
      // Create a new context.
      v8::Local&lt;v8::Context&gt; context = v8::Context::New(instance-&gt;isolate);
  
      // Enter the context for compiling and running the hello world script.
      v8::Context::Scope context_scope(context);
  
      {
          // Create a string containing the JavaScript source code.
          v8::Local&lt;v8::String&gt; source =
            v8::String::NewFromUtf8(instance-&gt;isolate, script,
            v8::NewStringType::kNormal).ToLocalChecked();
  
          // Compile the source code.
          v8::Local&lt;v8::Script&gt; script =
            v8::Script::Compile(context, source).ToLocalChecked();
  
          // Run the script to get the result.
          v8::Local&lt;v8::Value&gt; result = script-&gt;Run(context).ToLocalChecked();
  
          // Convert the result to an UTF8 string and print it.
          v8::String::Utf8Value utf8(instance-&gt;isolate, result);
          printf("%s\n", *utf8);
      }
  }
  }
  </code></pre>
  
  <p>Using these 3 files, I have built a .so file. Now my testing code looks as below.</p>
  
  <h2>4. main.c</h2>
  
  <pre><code>int main(int argc, char **argv)
  {
      int len;
      char *script;
      void *instance;
  
      instance = mjse_create_instance(argv);
  
      script =    "function js_add_elements1(var1, var2) \
                  { \
                      var var3 = parseInt(var1) + parseInt(var2); \
                      var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
                      return result; \
                  };\
                  js_add_elements1(2, 3);";
  
      len = strlen(script);
      mjse_execute_script(instance, script, len);
  
      script =    "function js_add_elements2(var1, var2) \
                  { \
                      var var3 = parseInt(var1) + parseInt(var2); \
                      var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
                      return result; \
                  };\
                  js_add_elements2(2, 3);";
  
      len = strlen(script);
      mjse_execute_script(instance, script, len);
  
      script =    "function js_add_elements3(var1, var2) \
                  { \
                      var var3 = parseInt(var1) + parseInt(var2); \
                      var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
                      return result; \
                  };\
                  js_add_elements3(2, 3);";
  
      len = strlen(script);
      mjse_execute_script(instance, script, len);
  
      mjse_destroy_instance(instance);
  
      return 0;
  }
  </code></pre>
  
  <p>With this, I built main.c and tested. The output looks as below.</p>
  
  <blockquote>
    <p>Version: 7.7.0 (candidate)<br> Addition of 2 and 3 results 5<br>
    Addition of 2 and 3 results 5<br> Addition of 2 and 3 results 5<br></p>
  </blockquote>
  
  <p>From functionality perspective it looks fine. However there quite a bunch of Conditional jumps and memory leaks as show below (only few to keep size less).</p>
  
  <pre><code>==31273== Conditional jump or move depends on uninitialised value(s)
  ==31273==    at 0x5DB55E8: v8::internal::DeclarationScope::CheckConflictingVarDeclarations() (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x599DCE8: v8::internal::PreParser::PreParseFunction(v8::internal::AstRawString const*, v8::internal::FunctionKind, v8::internal::FunctionLiteral::FunctionType, v8::internal::DeclarationScope*, int*, v8::internal::ProducedPreparseData**, int) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x597C6B5: v8::internal::Parser::SkipFunction(v8::internal::AstRawString const*, v8::internal::FunctionKind, v8::internal::FunctionLiteral::FunctionType, v8::internal::DeclarationScope*, int*, int*, v8::internal::ProducedPreparseData**) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x5970495: v8::internal::Parser::ParseFunctionLiteral(v8::internal::AstRawString const*, v8::internal::Scanner::Location, v8::internal::FunctionNameValidity, v8::internal::FunctionKind, int, v8::internal::FunctionLiteral::FunctionType, v8::internal::LanguageMode, v8::internal::ZoneList&lt;v8::internal::AstRawString const*&gt;*) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x5996C7A: v8::internal::ParserBase&lt;v8::internal::Parser&gt;::ParseHoistableDeclaration(int, v8::base::Flags&lt;v8::internal::ParseFunctionFlag, int&gt;, v8::internal::ZoneList&lt;v8::internal::AstRawString const*&gt;*, bool) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x596EFE6: v8::internal::Parser::DoParseProgram(v8::internal::Isolate*, v8::internal::ParseInfo*) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x596E6D8: v8::internal::Parser::ParseProgram(v8::internal::Isolate*, v8::internal::ParseInfo*) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x599A4D9: v8::internal::parsing::ParseProgram(v8::internal::ParseInfo*, v8::internal::Isolate*) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x56EF5B5: v8::internal::(anonymous namespace)::CompileToplevel(v8::internal::ParseInfo*, v8::internal::Isolate*, v8::internal::IsCompiledScope*) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x56F0EA8: v8::internal::Compiler::GetSharedFunctionInfoForScript(v8::internal::Isolate*, v8::internal::Handle&lt;v8::internal::String&gt;, v8::internal::Compiler::ScriptDetails const&amp;, v8::ScriptOriginOptions, v8::Extension*, v8::internal::ScriptData*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason, v8::internal::NativesFlag) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x56B5C64: v8::ScriptCompiler::CompileUnboundInternal(v8::Isolate*, v8::ScriptCompiler::Source*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273==    by 0x56B6356: v8::ScriptCompiler::Compile(v8::Local&lt;v8::Context&gt;, v8::ScriptCompiler::Source*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason) (in /usr/local/mysys/system/libs/libmjse.so)
  ==31273== 
  
  ==31273==    LEAK SUMMARY:&lt;br&gt;
  ==31273==    definitely lost: 144 bytes in 1 blocks&lt;br&gt;
  ==31273==    indirectly lost: 1,744 bytes in 11 blocks&lt;br&gt;
  ==31273==    possibly lost: 960 bytes in 3 blocks&lt;br&gt;
  ==31273==    still reachable: 1,474 bytes in 18 blocks&lt;br&gt;
  ==31273==    suppressed: 0 bytes in 0 blocks&lt;br&gt;
  </code></pre>
  
  <p>Not sure whats wrong here. Any help in this regard, highly appreciated.</p>
  
  <h2>EDIT</h2>
  
  <p>After modifying code as suggested by Radosław Cybulski, memory leaks are gone. Only still reachable memory 168 bytes present.</p>
  
  <p>However still conditional jump for uninitialised values are present (with valgrind run). One thing I observe if I remove function arguments in javascript, these conditional jump for uninitialised values are not showing. Say I will have javascript as below.</p>
  
  <pre><code>char *jscript =  "function js_add_elements1() \
      { \
          return 10; \
      };\
  
  js_add_elements1();";
  </code></pre>
  
  <p>With javascript as above, I do not see conditional memory jumps for uninitialised values. What could be the reason?</p>