You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MFC嵌入V8 10.5.0调用Context::New创建上下文触发崩溃求助

问题环境
  • V8版本:10.5.0
  • 开发IDE:Visual Studio 2022
  • 场景:MFC对话框项目嵌入V8引擎,OnInitDialog中初始化V8,OnDestroy中释放V8相关资源,按钮BN_CLICKED事件中编写创建上下文、执行"Hello World!"脚本逻辑,预期点击按钮输出对应结果,但执行创建上下文代码时触发崩溃。相同逻辑在控制台程序下运行无异常。
复现代码

头文件定义

class Cv8TestDlg : public CDialogEx
{
    ...

    v8::Isolate::CreateParams m_create_params;
    v8::Isolate* m_isolate = nullptr;

    virtual BOOL OnInitDialog();

    ...

    afx_msg void OnDestroy();
    afx_msg void OnRun();
};

实现代码

BOOL Cv8TestDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    ...

    // Initialize V8.
    v8::V8::InitializeICUDefaultLocation("");
    v8::V8::InitializeExternalStartupData("");
    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.
    m_create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
    m_isolate = v8::Isolate::New(m_create_params);

    return TRUE;
}

void Cv8TestDlg::OnDestroy()
{
    CDialogEx::OnDestroy();

    m_isolate->Dispose();
    v8::V8::Dispose();
    v8::V8::DisposePlatform();
    delete m_create_params.array_buffer_allocator;
}

void Cv8TestDlg::OnRun()
{
    CString text;
    v8::Isolate* isolate = m_isolate;

    v8::Isolate::Scope isolate_scope(isolate);

    // Create a stack-allocated handle scope.
    v8::HandleScope handle_scope(isolate);

    // Create a new context.
    v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr);

    // 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<v8::String> source = v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");

        // Compile the source code.
        v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();

        // Run the script to get the result.
        v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

        // Convert the result to an UTF8 string and print it.
        v8::String::Value utf8(isolate, result);
        text = (LPCWSTR)*utf8;
    }

    GetDlgItem(IDC_EDIT1)->SetWindowText(text);
}
崩溃信息
  • 触发崩溃代码行:v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr);
  • 异常信息:(0x00007FFADBB43D53(v8.dll), v8Test.exe): 0xC0000005: 0x0000000000000088 access violation
  • 崩溃调用栈:
v8.dll!v8::internal::tracing::TraceEventHelper::GetTracingController() 
v8.dll!v8::NewContext(v8::Isolate * external_isolate, v8::ExtensionConfiguration * extensions, v8::MaybeLocal<v8::ObjectTemplate> global_template, v8::MaybeLocal<v8::Value> global_object, unsigned __int64 context_snapshot_index, v8::DeserializeInternalFieldsCallback embedder_fields_deserializer, v8::MicrotaskQueue * microtask_queue) line 6391    C++
v8.dll!v8::Context::New(v8::Isolate * external_isolate, v8::ExtensionConfiguration * extensions, v8::MaybeLocal<v8::ObjectTemplate> global_template, v8::MaybeLocal<v8::Value> global_object, v8::DeserializeInternalFieldsCallback internal_fields_deserializer, v8::MicrotaskQueue * microtask_queue) line 6413   C++
v8Test.exe!Cv8TestDlg::OnRun() line 198 C++
  • 崩溃断点位置(trace-event.cc):
v8::TracingController* TraceEventHelper::GetTracingController() {
->  return v8::internal::V8::GetCurrentPlatform()->GetTracingController();
}
问题根因

V8 Platform实例生命周期管理错误。
OnInitDialog中定义的std::unique_ptr<v8::Platform> platform是函数内局部栈变量,OnInitDialog执行完成返回时,该变量会被unique_ptr自动析构释放,V8内部保存的平台指针直接变成野指针。后续点击按钮调用Context::New时,V8尝试通过GetCurrentPlatform()获取平台对象读取TracingController,访问已释放内存就触发了访问冲突崩溃。
控制台程序相同逻辑不崩溃的原因是,控制台一般将platform定义在main函数内,main函数在程序整个运行周期不会退出,platform对象会一直存活到程序结束,不会出现提前释放问题。

修复方案

将platform的生存期延长到和V8引擎使用周期一致即可,最简单的方式是把它改为对话框类的成员变量,和m_isolate、m_create_params统一管理:

  1. 在头文件类定义中新增platform成员:
class Cv8TestDlg : public CDialogEx
{
    ...
    std::unique_ptr<v8::Platform> m_platform; // 新增成员
    v8::Isolate::CreateParams m_create_params;
    v8::Isolate* m_isolate = nullptr;
    ...
};
  1. 修改OnInitDialog初始化逻辑,去掉局部platform变量,直接给成员变量赋值:
// Initialize V8.
v8::V8::InitializeICUDefaultLocation("");
v8::V8::InitializeExternalStartupData("");
m_platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(m_platform.get());
v8::V8::Initialize();
  1. 现有OnDestroy释放逻辑不需要额外修改,m_platform会在DisposePlatform执行完成、函数退出时自动析构,符合资源初始化逆序释放的要求。

内容的提问来源于stack exchange,提问作者오병학

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:03:17