c++ - 使用 Global with Value 时的 V8 段错误

标签 c++ v8 embedded-v8

我开始嵌入 v8,但遇到了一些“意外行为”。当变量 value_ 最后不是 Reset 时,以下代码会产生 Segmentation fault (core dumped)(请参阅代码中的注释)。但是,这不适用于上下文 context_。为什么? This answer似乎相关但不提供解释。

我的期望是 isolate->Dispose() 会兼顾这两者。

#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设置:

按照官方 Getting started with embedding V8运行示例 中的说明进行操作.将代码保存到 sample/wasm.cc 并执行以下命令:

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

最佳答案

因此,如果您不调用 Global::Reset() ,但是Dispose Isolate在销毁之前 Global , Global 的析构函数会导致释放后访问,这是典型的未定义行为。

Reset()会将内部指针设置为 nullptr ,随后的调用将检查这个事实并且不做任何事情。这就是为什么你可以添加 Reset()之前Dispose()避免UB。

您的 Global<Context> 也是如此,它不会 self 证明,因为释放后访问并不总是触发段错误。

关于c++ - 使用 Global with Value 时的 V8 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53982229/

相关文章:

C++ 寻找 String.Replace()

javascript - V8 实际上在哪里使用原始 javascript 代码?

c++ - 在x86/x86-64上智能指针的原子交换

c++ - 自动工具 : how to set global compilation flag

c++ - 给定一个字符串数组,返回所有是变位词的字符串组

c++ - 在 Node.js 和 v8 中调用使用包装对象作为参数的函数

javascript - 如何在 Node.js 中获得微时间?

java - Google V8 的工作方式与 Java 虚拟机类似吗?

node.js - 是否可以跳过 v8 GC 收集的对象?

c99 - 将 Google V8 嵌入 ANSI C 应用程序 - 从哪里开始?