我在制作以下代码时遇到了一些麻烦。它是https://github.com/v8/v8/wiki/Embedders-Guide#accessing-dynamic-variables处发现的材料的略微延伸。它的不同之处在于它除了对象之外还有对象的构造函数。代码将成功运行,但会泄漏本机| PointAndPersistent |在| PointConstructor |中分配。我试图根据我在d8(https://cs.chromium.org/chromium/src/v8/src/d8.cc?q=DataAndPersistent&sq=package:chromium&l=215)中找到的一些代码,使用| SetWeak |来提供回调来清理它,但它永远不会被执行。有谁知道实现这个目标的正确方法是什么?
#include <cstdio>
#include "v8/include/libplatform/libplatform.h"
#include "v8/include/v8.h"
using namespace v8;
struct PointAndPersistent {
int x;
int y;
Global<Object> wrapper;
};
void PointAndPersistentCallback(
const WeakCallbackInfo<PointAndPersistent>& data) {
data.GetParameter()->wrapper.Reset();
delete data.GetParameter();
}
void PointConstructor(const FunctionCallbackInfo<Value>& args) {
PointAndPersistent* point_and_persistent = new PointAndPersistent();
if (args.Length() > 0) {
point_and_persistent->x = args[0]->Int32Value();
}
if (args.Length() > 1) {
point_and_persistent->y = args[1]->Int32Value();
}
point_and_persistent->wrapper.Reset(args.GetIsolate(), args.This());
point_and_persistent->wrapper.SetWeak(point_and_persistent,
PointAndPersistentCallback,
v8::WeakCallbackType::kParameter);
point_and_persistent->wrapper.MarkIndependent();
args.This()->SetInternalField(0,
External::New(args.GetIsolate(), point_and_persistent));
args.GetReturnValue().Set(args.This());
}
void GetPointX(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
int value = static_cast<PointAndPersistent*>(ptr)->x;
info.GetReturnValue().Set(value);
}
void SetPointX(Local<String> property, Local<Value> value,
const PropertyCallbackInfo<void>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<PointAndPersistent*>(ptr)->x = value->Int32Value();
}
void GetPointY(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
int value = static_cast<PointAndPersistent*>(ptr)->y;
info.GetReturnValue().Set(value);
}
void SetPointY(Local<String> property, Local<Value> value,
const PropertyCallbackInfo<void>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<PointAndPersistent*>(ptr)->y = value->Int32Value();
}
int main() {
Platform* platform = platform::CreateDefaultPlatform();
V8::InitializePlatform(platform);
V8::Initialize();
Isolate::CreateParams params;
params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(params);
{
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<FunctionTemplate> point_constructor_template =
FunctionTemplate::New(isolate, PointConstructor);
point_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
point_constructor_template->InstanceTemplate()->SetAccessor(
String::NewFromUtf8(isolate, "x"), GetPointX, SetPointX);
point_constructor_template->InstanceTemplate()->SetAccessor(
String::NewFromUtf8(isolate, "y"), GetPointY, SetPointY);
Local<ObjectTemplate> point_template =
ObjectTemplate::New(isolate, point_constructor_template);
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Local<String> name =
String::NewFromUtf8(isolate, "Point", NewStringType::kNormal)
.ToLocalChecked();
global_template->Set(name, point_constructor_template);
Local<Context> context = Context::New(isolate, nullptr, global_template);
Context::Scope context_scope(context);
Local<String> source = String::NewFromUtf8(isolate, "new Point(1, 2).x;",
NewStringType::kNormal)
.ToLocalChecked();
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
Local<Value> result = script->Run(context).ToLocalChecked();
String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
isolate->Dispose();
V8::Dispose();
V8::ShutdownPlatform();
delete platform;
delete params.array_buffer_allocator;
}
谢谢!
答案 0 :(得分:0)
当垃圾收集器确定可以释放对象时,将调用弱回调。像你的例子一样的短期运行程序不需要运行垃圾收集器。
您可以尝试在关闭应用之前强制执行GC循环。当然这会使你的关机变慢。
对于记录,SetWeak
的{{3}}说:
注意:无法保证何时甚至如果回调是 调用。调用仅在尽力而为的基础上执行。 与往常一样,基于GC的终结应该不依赖于任何 资源管理的关键形式!