V8 Segfault when using Global with Value












2















I am getting started with embedding v8 and I am encountering some 'unexpected behavior'. The following code produces a Segmentation fault (core dumped) when the variable value_ is not Reset at the end (see comment in code). However, the same does not apply for the context context_. Why? This answer seems to be related but does not provide an explanation.



My expectation was that isolate->Dispose() takes care of both.



#include <stdlib.h>

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

int main(int argc, char* argv) {
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();

{
// Initialize V8.
// 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);
v8::Global<v8::Context> context_;
v8::Global<v8::String> value_;
{
// Global Context Setup
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);

v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);

v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
context_.Reset(isolate, context);

// Global Value Setup
v8::Context::Scope context_scope(context);
v8::Local<v8::String> value = v8::String::NewFromUtf8(isolate, "segfault", v8::NewStringType::kNormal).ToLocalChecked();
value_.Reset(isolate, value);
}

// value_.Reset(); // <- Why is this line needed?
// context_.Reset(); // <- Why is this line NOT needed?
isolate->Dispose();
delete create_params.array_buffer_allocator;
}

v8::V8::Dispose();
v8::V8::ShutdownPlatform();
return 0;
}


Build setup:



Follow the instruction in Run the example from the official Getting started with embedding V8. Save the code to sample/wasm.cc and execute following commands:



$ g++ -I. -O2 -Iinclude samples/segfault.cc -o segfault  -lv8_monolith -Lout.gn/x64.release.sample/obj/ -pthread -std=c++17
$ ./segfault









share|improve this question





























    2















    I am getting started with embedding v8 and I am encountering some 'unexpected behavior'. The following code produces a Segmentation fault (core dumped) when the variable value_ is not Reset at the end (see comment in code). However, the same does not apply for the context context_. Why? This answer seems to be related but does not provide an explanation.



    My expectation was that isolate->Dispose() takes care of both.



    #include <stdlib.h>

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

    int main(int argc, char* argv) {
    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();

    {
    // Initialize V8.
    // 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);
    v8::Global<v8::Context> context_;
    v8::Global<v8::String> value_;
    {
    // Global Context Setup
    v8::Isolate::Scope isolate_scope(isolate);
    v8::HandleScope handle_scope(isolate);

    v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);

    v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
    context_.Reset(isolate, context);

    // Global Value Setup
    v8::Context::Scope context_scope(context);
    v8::Local<v8::String> value = v8::String::NewFromUtf8(isolate, "segfault", v8::NewStringType::kNormal).ToLocalChecked();
    value_.Reset(isolate, value);
    }

    // value_.Reset(); // <- Why is this line needed?
    // context_.Reset(); // <- Why is this line NOT needed?
    isolate->Dispose();
    delete create_params.array_buffer_allocator;
    }

    v8::V8::Dispose();
    v8::V8::ShutdownPlatform();
    return 0;
    }


    Build setup:



    Follow the instruction in Run the example from the official Getting started with embedding V8. Save the code to sample/wasm.cc and execute following commands:



    $ g++ -I. -O2 -Iinclude samples/segfault.cc -o segfault  -lv8_monolith -Lout.gn/x64.release.sample/obj/ -pthread -std=c++17
    $ ./segfault









    share|improve this question



























      2












      2








      2








      I am getting started with embedding v8 and I am encountering some 'unexpected behavior'. The following code produces a Segmentation fault (core dumped) when the variable value_ is not Reset at the end (see comment in code). However, the same does not apply for the context context_. Why? This answer seems to be related but does not provide an explanation.



      My expectation was that isolate->Dispose() takes care of both.



      #include <stdlib.h>

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

      int main(int argc, char* argv) {
      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();

      {
      // Initialize V8.
      // 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);
      v8::Global<v8::Context> context_;
      v8::Global<v8::String> value_;
      {
      // Global Context Setup
      v8::Isolate::Scope isolate_scope(isolate);
      v8::HandleScope handle_scope(isolate);

      v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);

      v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
      context_.Reset(isolate, context);

      // Global Value Setup
      v8::Context::Scope context_scope(context);
      v8::Local<v8::String> value = v8::String::NewFromUtf8(isolate, "segfault", v8::NewStringType::kNormal).ToLocalChecked();
      value_.Reset(isolate, value);
      }

      // value_.Reset(); // <- Why is this line needed?
      // context_.Reset(); // <- Why is this line NOT needed?
      isolate->Dispose();
      delete create_params.array_buffer_allocator;
      }

      v8::V8::Dispose();
      v8::V8::ShutdownPlatform();
      return 0;
      }


      Build setup:



      Follow the instruction in Run the example from the official Getting started with embedding V8. Save the code to sample/wasm.cc and execute following commands:



      $ g++ -I. -O2 -Iinclude samples/segfault.cc -o segfault  -lv8_monolith -Lout.gn/x64.release.sample/obj/ -pthread -std=c++17
      $ ./segfault









      share|improve this question
















      I am getting started with embedding v8 and I am encountering some 'unexpected behavior'. The following code produces a Segmentation fault (core dumped) when the variable value_ is not Reset at the end (see comment in code). However, the same does not apply for the context context_. Why? This answer seems to be related but does not provide an explanation.



      My expectation was that isolate->Dispose() takes care of both.



      #include <stdlib.h>

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

      int main(int argc, char* argv) {
      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();

      {
      // Initialize V8.
      // 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);
      v8::Global<v8::Context> context_;
      v8::Global<v8::String> value_;
      {
      // Global Context Setup
      v8::Isolate::Scope isolate_scope(isolate);
      v8::HandleScope handle_scope(isolate);

      v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);

      v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
      context_.Reset(isolate, context);

      // Global Value Setup
      v8::Context::Scope context_scope(context);
      v8::Local<v8::String> value = v8::String::NewFromUtf8(isolate, "segfault", v8::NewStringType::kNormal).ToLocalChecked();
      value_.Reset(isolate, value);
      }

      // value_.Reset(); // <- Why is this line needed?
      // context_.Reset(); // <- Why is this line NOT needed?
      isolate->Dispose();
      delete create_params.array_buffer_allocator;
      }

      v8::V8::Dispose();
      v8::V8::ShutdownPlatform();
      return 0;
      }


      Build setup:



      Follow the instruction in Run the example from the official Getting started with embedding V8. Save the code to sample/wasm.cc and execute following commands:



      $ g++ -I. -O2 -Iinclude samples/segfault.cc -o segfault  -lv8_monolith -Lout.gn/x64.release.sample/obj/ -pthread -std=c++17
      $ ./segfault






      c++ v8 embedded-v8






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 30 '18 at 23:55







      mhk

















      asked Dec 30 '18 at 23:20









      mhkmhk

      254




      254
























          1 Answer
          1






          active

          oldest

          votes


















          0















          • v8::Global has a destructor that will call Reset().


          • The global handles are held in the Isolate, after Isolate::Dispose(), the global handles will be freed.



          Thus, if you don't call Global::Reset(), but Dispose the Isolate before the destruction of a Global, the destructor of Global will cause a access-after-free, which is a typical Undefined Behavior.



          Reset() will set the internal pointer to nullptr, and subsequent call will check this fact and doesn't do anything. That's why you can add a Reset() before Dispose() to avoid the UB.



          That's also true for your Global<Context>, it doesn't demonstrate itself because access-after-free doesn't always trigger a segfault.






          share|improve this answer
























          • Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

            – mhk
            Dec 31 '18 at 15:10











          • @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

            – llllllllll
            Dec 31 '18 at 15:15













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53982229%2fv8-segfault-when-using-global-with-value%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0















          • v8::Global has a destructor that will call Reset().


          • The global handles are held in the Isolate, after Isolate::Dispose(), the global handles will be freed.



          Thus, if you don't call Global::Reset(), but Dispose the Isolate before the destruction of a Global, the destructor of Global will cause a access-after-free, which is a typical Undefined Behavior.



          Reset() will set the internal pointer to nullptr, and subsequent call will check this fact and doesn't do anything. That's why you can add a Reset() before Dispose() to avoid the UB.



          That's also true for your Global<Context>, it doesn't demonstrate itself because access-after-free doesn't always trigger a segfault.






          share|improve this answer
























          • Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

            – mhk
            Dec 31 '18 at 15:10











          • @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

            – llllllllll
            Dec 31 '18 at 15:15


















          0















          • v8::Global has a destructor that will call Reset().


          • The global handles are held in the Isolate, after Isolate::Dispose(), the global handles will be freed.



          Thus, if you don't call Global::Reset(), but Dispose the Isolate before the destruction of a Global, the destructor of Global will cause a access-after-free, which is a typical Undefined Behavior.



          Reset() will set the internal pointer to nullptr, and subsequent call will check this fact and doesn't do anything. That's why you can add a Reset() before Dispose() to avoid the UB.



          That's also true for your Global<Context>, it doesn't demonstrate itself because access-after-free doesn't always trigger a segfault.






          share|improve this answer
























          • Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

            – mhk
            Dec 31 '18 at 15:10











          • @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

            – llllllllll
            Dec 31 '18 at 15:15
















          0












          0








          0








          • v8::Global has a destructor that will call Reset().


          • The global handles are held in the Isolate, after Isolate::Dispose(), the global handles will be freed.



          Thus, if you don't call Global::Reset(), but Dispose the Isolate before the destruction of a Global, the destructor of Global will cause a access-after-free, which is a typical Undefined Behavior.



          Reset() will set the internal pointer to nullptr, and subsequent call will check this fact and doesn't do anything. That's why you can add a Reset() before Dispose() to avoid the UB.



          That's also true for your Global<Context>, it doesn't demonstrate itself because access-after-free doesn't always trigger a segfault.






          share|improve this answer














          • v8::Global has a destructor that will call Reset().


          • The global handles are held in the Isolate, after Isolate::Dispose(), the global handles will be freed.



          Thus, if you don't call Global::Reset(), but Dispose the Isolate before the destruction of a Global, the destructor of Global will cause a access-after-free, which is a typical Undefined Behavior.



          Reset() will set the internal pointer to nullptr, and subsequent call will check this fact and doesn't do anything. That's why you can add a Reset() before Dispose() to avoid the UB.



          That's also true for your Global<Context>, it doesn't demonstrate itself because access-after-free doesn't always trigger a segfault.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 31 '18 at 6:14









          llllllllllllllllllll

          13.7k41742




          13.7k41742













          • Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

            – mhk
            Dec 31 '18 at 15:10











          • @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

            – llllllllll
            Dec 31 '18 at 15:15





















          • Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

            – mhk
            Dec 31 '18 at 15:10











          • @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

            – llllllllll
            Dec 31 '18 at 15:15



















          Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

          – mhk
          Dec 31 '18 at 15:10





          Is there a reason, why Global::Reset() is not automatically called on all registered global objects when Isolate::Dispose() is invoked?

          – mhk
          Dec 31 '18 at 15:10













          @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

          – llllllllll
          Dec 31 '18 at 15:15







          @mhk Global essentially contains a pointer to the storage node. Isolate has no way to change that pointer value. Because Isolate doesn't know where the Global is in user's code.

          – llllllllll
          Dec 31 '18 at 15:15




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53982229%2fv8-segfault-when-using-global-with-value%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Mossoró

          Error while reading .h5 file using the rhdf5 package in R

          Pushsharp Apns notification error: 'InvalidToken'