首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >迭代时V8崩溃

迭代时V8崩溃
EN

Stack Overflow用户
提问于 2022-09-19 13:20:17
回答 1查看 84关注 0票数 0

我一直试图将V8 javascript引擎嵌入到我的项目中。在大多数情况下,这是成功的,但有一个问题似乎没有消失,我不知道是什么原因。

当我编写一个简单的for循环来迭代包含数千个条目的数组时,V8分段错误。瓦兰德说:

代码语言:javascript
运行
复制
==38120== Invalid read of size 8
==38120==    at 0x525F654: v8::internal::Isolate::main_thread_local_heap() (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x53A532A: v8::internal::interpreter::BytecodeArrayIterator::BytecodeArrayIterator(v8::internal::Handle<v8::internal::BytecodeArray>, int) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5C01534: v8::internal::baseline::BaselineCompiler::BaselineCompiler(v8::internal::LocalIsolate*, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Handle<v8::internal::BytecodeArray>) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5C143E9: v8::internal::GenerateBaselineCode(v8::internal::Isolate*, v8::internal::Handle<v8::internal::SharedFunctionInfo>) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x51D796E: v8::internal::Compiler::CompileSharedWithBaseline(v8::internal::Isolate*, v8::internal::Handle<v8::internal::SharedFunctionInfo>, v8::internal::Compiler::ClearExceptionFlag, v8::internal::IsCompiledScope*) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x51D7CF5: v8::internal::Compiler::CompileBaseline(v8::internal::Isolate*, v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Compiler::ClearExceptionFlag, v8::internal::IsCompiledScope*) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5BFF355: v8::internal::baseline::BaselineBatchCompiler::CompileBatch(v8::internal::Handle<v8::internal::JSFunction>) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5BFEF8E: v8::internal::baseline::BaselineBatchCompiler::EnqueueFunction(v8::internal::Handle<v8::internal::JSFunction>) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5276501: v8::internal::TieringManager::OnInterruptTick(v8::internal::Handle<v8::internal::JSFunction>) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5D8BA69: v8::internal::Runtime_BytecodeBudgetInterruptWithStackCheck(int, unsigned long*, v8::internal::Isolate*) (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5AEA9F7: Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit (in /home/ktp/oma/lib/liboma_js.so)
==38120==    by 0x5B98E62: Builtins_JumpLoopHandler (in /home/ktp/oma/lib/liboma_js.so)
==38120==  Address 0xf100 is not stack'd, malloc'd or (recently) free'd

我的绑定和设置很大程度上是基于v8.dev的嵌入指南中的示例,尽管它封装在一个类中,并且使用V8:platform::PumpMessageLoop()调用了epoll循环中运行在与V8相同线程中的timerfd。

JS代码导致val差利消息是这样的:

代码语言:javascript
运行
复制
var g = new Array(1024*16);

g.fill(0);

for(var i in g)
{
    i+i;
}

当数组的大小为最大1024*7时,JS代码工作,当我打印迭代计数时,它在7500左右崩溃。

编辑:这个C++代码提供了相同的错误,并且是我使用的代码的缩短版本:

代码语言:javascript
运行
复制
#include <v8.h>
#include <v8-context.h>
#include <v8-isolate.h>
#include <v8-local-handle.h>
#include <v8-primitive.h>
#include <v8-script.h>
#include <v8-json.h>
#include <libplatform/libplatform.h>

int main(int argc, char *argv[])
{    
    // Initialize V8.
    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();
    // 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);
    std::string src = R"(
    for(var i=0;i<1024*8;i++)
    {
    }
    )";

{
    v8::HandleScope handle_scope(isolate); 
    v8::Local<v8::Context> ctx = v8::Context::New(isolate); 
    v8::Context::Scope context_scope(ctx);

    v8::MaybeLocal<v8::String> vsrc = v8::String::NewFromUtf8(isolate, src.c_str(), v8::NewStringType::kNormal, static_cast<int>(src.size()));

    v8::MaybeLocal<v8::Script> script = v8::Script::Compile(ctx, vsrc.ToLocalChecked()).ToLocalChecked();
    if(script.IsEmpty())
    {
        printf("error0\n");
    }
    
    v8::MaybeLocal<v8::Value> result = script.ToLocalChecked()->Run(ctx);
    
    if(result.IsEmpty())
    {
        printf("error1\n");  
    }
}

isolate->Dispose();
v8::V8::Dispose();
v8::V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
}

示例是用以下命令编译的:

代码语言:javascript
运行
复制
g++ -c /home/ktp/oma/src/jx.cpp -DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX -I/home/ktp/v8/v8/include/ -fPIC -Wall -g -std=c++17
g++ -o /home/ktp/oma/bin/jx jx.o -DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX -lv8_monolith -ldl -lpthread -L/home/ktp/v8/v8/out.gn/x64.release.sample/obj/

我不完全确定V8版本,但我在30.8上构建了它。d8控制台显示V8版本为10.7.0。

V8是根据v8.dev和https://v8.dev/docs/source-code#using-git上的说明构建的:

代码语言:javascript
运行
复制
tools/dev/v8gen.py x64.release.sample
ninja -C out.gn/x64.release.sample v8_monolith

gn args说:

代码语言:javascript
运行
复制
dcheck_always_on = false
is_component_build = false
is_debug = false
target_cpu = "x64"
use_custom_libcxx = false
v8_enable_sandbox = true
v8_monolithic = true
v8_use_external_startup_data = false
EN

回答 1

Stack Overflow用户

发布于 2022-09-19 19:02:05

您需要输入Isolate。您可以使用isolate->Enter()isolate->Exit(),也可以使用v8::Isolate::Scope isolate_scope(isolate) (这是这两个步骤的方便包装器),介于创建隔离和创建HandleScope之间。

帮助你自己:

  1. 将GN (使用gn args out/x64.release.sample)更改为is_debug = true,以获得调试版本,并重新编译。
  2. 在调试器中运行调试二进制程序,例如gdb -args /home/ktp/oma/bin/jx (或您喜欢使用的调试器)。
  3. 在这种情况下,您甚至不需要花哨的调试特性,因为Debug构建包含一个失败的检查:Debug check failed: (isolate) != nullptr。如果您请求回溯跟踪,您将看到这发生在V8内部的某个地方;幸运的是,在这种情况下,细节并不重要。
  4. 有了这些知识,您可以将您的代码与一些工作示例进行比较,例如V8的壳样,并查看它是否对代码没有执行的隔离进行任何操作。Isolate::Scope显然是一个潜在的嫌疑人。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73774024

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档