我对V8如何管理其内存感到困惑。
问题:
据我所知,V8基本上使用Handle来引用内存中的实例,而使用HandleScope,可以自动轻松地管理所有本地句柄。但我无法理解为什么FunctionCallbackInfo不使用Handle来保持返回值:
void MyMethod(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
cout<<"totally "<<args.Length()<<" arguments"<<endl;
int result = AddOpeation(args[0]->Int32Value(), args[1]->Int32Value());
char *s = new char [10];
ZeroMemory(s, 10);
_itoa_s(result, s, 9, 10);
args.GetReturnValue().Set(String::NewFromUtf8(isolate, s)); // I'm confused by this line of code !!!
delete [] s;
}
以下是 FunctionCallbackInfo :: GetReturnValue
的实现template<typename T>
ReturnValue<T> FunctionCallbackInfo<T>::GetReturnValue() const {
return ReturnValue<T>(&implicit_args_[kReturnValueIndex]);
}
这是 ReturnValue :: Set :
的实现template<typename T>
template<typename S>
void ReturnValue<T>::Set(const Handle<S> handle) {
TYPE_CHECK(T, S);
if (V8_UNLIKELY(handle.IsEmpty())) {
*value_ = GetDefaultValue();
} else {
*value_ = *reinterpret_cast<internal::Object**>(*handle);
}
以下是 ReturnValue :: value _ :
的定义 ...
V8_INLINE void SetInternal(internal::Object* value) { *value_ = value; }
V8_INLINE internal::Object* GetDefaultValue();
V8_INLINE explicit ReturnValue(internal::Object** slot);
internal::Object** value_;
问题:
回到我的代码 - 函数MyMethod,因为 ReturnValue :: value _ 不是句柄,一旦HandleScope被销毁就可以安全地访问ReturnValue :: value_吗?
我猜:
如果我创建了两个类的实例:
HandleScope s0(...);
LocalHandle<FunctionCallbackInfo> h0 = ...;
...
{
HandleScope s1(...);
LocalHandle<MyType> h1 = ...;
h0.ptr = *h1; // Suppose ptr is a member field defined in FunctionCallbackInfo
}
S1将在S0之前被销毁,此时,因为s0仍然存在,h0也是如此,并且* h1是h0的成员字段,因此V8 GC不会清理* h1或h0.ptr引用的内存。
我的猜测合理吗?
答案 0 :(得分:0)
v8::HandleScope
将销毁作用域出口上的所有本地句柄。我想没有办法通知句柄范围哪个句柄是结果而不应该被销毁。但v8::EscapableHandleScope
允许这样做:
void MyMethod(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = Isolate::GetCurrent();
EscapableHandleScope scope(isolate);
int result = AddOpeation(args[0]->Int32Value(), args[1]->Int32Value());
char s[10];
_itoa_s(result, s, 9, 10);
Local<String> result = String::NewFromUtf8(isolate, s);
args.GetReturnValue().Set(scope.Escape(result));
}
请参阅V8指南中Handles and Garbage Collection部分的底部。