javascript - 无法在 V8 C++ 嵌入中重新运行已编译的脚本
问题描述
我试图在给定的上下文/范围内重新运行 V8 脚本,但我遇到了分段错误。如果我编译其他脚本并连续运行它就可以了。
int loadScript(const char * scriptCode) {
v8::Local<v8::String> source =
v8::String::NewFromUtf8(isolate, scriptCode,
v8::NewStringType::kNormal)
.ToLocalChecked();
// Compile the source code.
script =
v8::Script::Compile(context, source).ToLocalChecked();
return 0;
}
std::string executeScript() {
// 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::Utf8Value utf8(isolate, result);
return std::string(*utf8);
}
////
sv8i.loadScript("let a = 1; \
let b = 2; \
JSON.stringify({a, b}); \
");
printf("%s\n", sv8i.executeScript().c_str());
printf("%s\n", sv8i.executeScript().c_str()); // Seg fault
结果是:
{"a":1,"b":2}
Thread 1 "spirit_v8_test" received signal SIGSEGV, Segmentation fault.
0x000055555585c9c8 in v8::internal::ScriptContextTable::Lookup(v8::internal::Isolate*, v8::internal::ScriptContextTable, v8::internal::String, v8::internal::VariableLookupResult*) ()
(gdb) backtrace
#0 0x000055555585c9c8 in v8::internal::ScriptContextTable::Lookup(v8::internal::Isolate*, v8::internal::ScriptContextTable, v8::internal::String, v8::internal::VariableLookupResult*) ()
#1 0x00005555556e3cfc in v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) ()
#2 0x00005555556e36a6 in v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) ()
#3 0x0000555555651990 in v8::Script::Run(v8::Local<v8::Context>) ()
#4 0x00005555556444b9 in SpiritV8Interface::executeScript[abi:cxx11]() (this=0x7fffffffe2b0) at ./spirit_bin_src/spirit_v8_interface.cpp:54
#5 0x00005555556446a9 in main (argc=1, argv=0x7fffffffe4a8) at ./spirit_bin_src/spirit_v8_interface.cpp:80
为什么?
解决方案
(1) 欢迎来到 StackOverflow!请注意,StackOverflow 不是“请为我调试代码”服务。从这个意义上说,有人可能会争辩说这个问题应该结束。
也就是说,这里还有一些可以说的东西,并且更普遍适用:
(2) 如果您确实需要一段代码的帮助,请发布一个完整的、可重现的示例。
在手头的案例中,缺少一些关键信息,这可以很好地解释出了什么问题:script
and的类型是context
什么?它们何时以及如何初始化?他们的寿命是多少?它们v8::Local
是 s,如果是,管理它们的 HandleScopes 在哪里?我敢打赌,问题出在这个领域的某个地方,但是除非您发布整个代码(足够完整,如果我愿意,我可以复制粘贴它并在本地运行它),否则很难确定。
(3)一旦你越过了segfault,你会遇到另一个问题:.ToLocalChecked()
意思是“我知道这MaybeLocal
不是空的,如果我错了它实际上是空的,那么我希望进程崩溃”。JavaScript 是一种非常适合异常处理的语言,因此作为 C++ 嵌入器,您必须处理几乎任何 JS 代码都可能抛出的可能性。这就是MaybeLocal
s 的用途:您可以检查它们是否包含值,或者异常是否阻止了结果值的返回。您还可以使用 av8::TryCatch
来捕获引发的异常,从而导致空MaybeLocal
.
更改 JavaScript 片段使其工作的事实在这里是一个很大的提示:运行let a = 1
在同一上下文中两次当然会抛出异常。如果你用 来“处理”它.ToLocalChecked()
,那么你就是在要求崩溃。
阅读 V8 的嵌入器文档可能会有所帮助,该文档更详细地解释了这些以及许多其他概念。(当您使用它时,也许还有一些 StackOverflow 介绍性文档。)
推荐阅读
- java - jedispool getResource 消耗太多延迟
- python - 在 DARKNET 培训期间获得 -NaN,我做错了什么?
- javascript - 有条件地分配数组索引
- java - 我怎样才能循环这个决策结构?
- webpack - Webpack:如何为 ES5 构建浏览器文件和为 Node:current 构建服务器文件
- php - Windows 2019 和 PHP 7.3:“session_start(): ps_files_cleanup_dir: opendir failed: No such file or directory (2)”
- c# - Web Scraper 未返回正确的 URL
- struct - 在通用 lisp 中将结构传递给宏的类型错误
- vbscript - Vbscript Sendkeys 在某些应用程序中不起作用
- php - WordPress 会话在主页之外无法正常工作