添加新模块实例时 V8PP / V8 崩溃

V8PP / V8 crashing when adding a new module instance

我希望能够创建 C++ classes 并将它们公开到 V8 JavaScript 引擎中。我用的是v8pp library to do this, and by following their examples as well as the Google V8 Hello World Script,我已经到了这个代码

// main.cpp

#define V8_COMPRESS_POINTERS

#include <v8.h>
#include <libplatform.h>

#include <v8pp/module.hpp>
#include <v8pp/class.hpp>

#include "src/TestClass1.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();

    v8::Isolate::CreateParams create_params;
    create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
    v8::Isolate *isolate = v8::Isolate::New(create_params);

    {
        v8::Isolate::Scope isolate_scope(isolate);
        v8::HandleScope handle_scope(isolate);
        v8::Local<v8::Context> context = v8::Context::New(isolate);

        v8pp::module window(isolate);
        v8pp::class_<TestClass1> TestClass1_V8(isolate);

        TestClass1_V8
                .ctor<int, int>()
                .set("a", v8pp::property(&TestClass1::getA, &TestClass1::setA))
                .set("b", v8pp::property(&TestClass1::getB, &TestClass1::setB))
                //.set_static("c", 5, true)
                .set("methodA", &TestClass1::testMethod);

        window.set("TestClass1", TestClass1_V8);
        isolate->GetCurrentContext()->Global()->Set(isolate->GetCurrentContext(), v8pp::to_v8(isolate, "window"), window.new_instance());

        v8::Context::Scope context_scope(context);

        {
            v8::Local<v8::String> source = v8::String::NewFromUtf8Literal(isolate, "(function() {let t = new window.TestClass1(); t.a = 5; return t.a})()");
            v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
            v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
            v8::String::Utf8Value utf8(isolate, result);
            printf("%s\n", *utf8);
        }
    }
    return 0;
}
// src/TestClass1.h

#ifndef V8PP_TESTCLASS1_H
#define V8PP_TESTCLASS1_H


class TestClass1 {
    friend int main(int argc, char* argv[]);

public:
    static int m_c;

    TestClass1(int a, int b) {
        m_a = a;
        m_b = b;
    }

    int testMethod(int c) {
        return m_a + m_b + c;
    }

private:
    int m_a;
    int m_b;

    int getA() {
        return m_a;
    }

    void setA(int a) {
        m_a = 2 * a;
    }

    int getB() {
        return m_b;
    }

    void setB(int b) {
        m_b = 3 + b;
    }
};

#endif //V8PP_TESTCLASS1_H
# CMakeList.txt
cmake_minimum_required(VERSION 3.19)
project(V8PP)

set(CMAKE_CXX_STANDARD 20)


### V8 ### [MANUAL]
set(CMAKE_CXX_FLAGS "/MT")
set(CMAKE_C_FLAGS "/MT")

if(MSVC)
    add_compile_options(
            $<$<CONFIG:>:/MT> #---------|
            $<$<CONFIG:Debug>:/MTd> #---|-- Statically link the runtime libraries
            $<$<CONFIG:Release>:/MT> #--|
    )
endif()

include_directories(E:/V8/depot_tools/v8/include)
include_directories(E:/V8/depot_tools/v8/include/libplatform)
include_directories(${CMAKE_SOURCE_DIR}/v8pp-master/v8pp-master)

link_directories(E:/V8/depot_tools/v8/out.gn/x64.release/obj/)
link_directories(E:/V8/depot_tools/v8/out.gn/x64.release/obj/third_party)
link_directories(E:/V8/depot_tools/v8/out.gn/x64.release/obj/third_party/icu)


link_libraries(
        v8_libbase
        v8_libplatform
        v8_monolith
        icuuc
        icui18n
)


link_libraries(winmm.lib)
link_libraries(dbghelp.lib)
link_libraries(shlwapi.lib)
### V8 ###


add_executable(V8PP main.cpp)

我已将错误隔离到行

isolate->GetCurrentContext()->Global()->Set(isolate->GetCurrentContext(), v8pp::to_v8(isolate, "window"), window.new_instance());

特别是 window.new_instance()。进入 v8pp 源代码(文件 module.hpp),方法中唯一的一行是

return obj_->NewInstance(isolate_->GetCurrentContext()).ToLocalChecked();

我将不同的语句分成不同的行,错误来自 obj_->NewInstance(),其中 obj_ 是一个 v8::Local<v8::ObjectTemplate>,在构造函数的初始化列表中创建模块对象。这个函数调用是v8本身的一部分,但我只能访问v8的头文件,所以我不知道是什么导致了错误。

代码构建良好,但是当它是 运行 时,没有回溯,只是:

Process finished with exit code -1073741819 (0xC0000005)

暗示内存访问错误(可能与指针有关?)

有谁知道如何在不发生此崩溃的情况下将 v8pp module 的新实例添加到 v8 引擎中?

编辑

使用:

我发现了问题:首先,我必须移动代码行

v8::Context::Scope context_scope(context);

到直下线

v8::Local<v8::Context> context = v8::Context::New(isolate);

这确实造成了另一个错误

#
# Fatal error in v8::ToLocalChecked
# Empty MaybeLocal.
#

<unknown>:21: Uncaught argument count does not match function definition

这是因为我在JavaScript中调用构造函数时忘记添加参数,所以将JavaScript代码更改为

(function() {let t = new window.TestClass1(); t.a = 5; return t.a;})()

一切正常。