大家好,我在写c++addon的时候有一个疑问,比如我在PlusOne这个方法里面有一个耗时的线程处理,每隔100ms触发一次js的回调函数,为什么我运行1分多钟之后,gc把MyObject对象给析构掉了?导致后面的程序出错了。请问这是什么原因导致的?如果我想实现这样的功能有没有其他的思路可以实现呢?附代码如下: // myobject.cc #include “myobject.h” #include <Windows.h> #include <vector> #include <string> #include <assert.h> using namespace std; using namespace v8;
Persistent<Function> MyObject::constructor; v8::Persistentv8::Function OnPlayRecordEnd; uv_async_t on_play_record_end_callback_;
typedef struct stSndUtilData { // 请求主体 //uv_async_t request_; // 回调处理函数 v8::Persistentv8::Function* callback_; // 回调数据队列 double pData_; }ST_SNDUTIL_DATA, *PT_ST_SNDUTIL_DATA;
void UV_Async_Handler(uv_async_t handle) { Isolate isolate = Isolate::GetCurrent(); HandleScope handle_scope(isolate); PT_ST_SNDUTIL_DATA data = (PT_ST_SNDUTIL_DATA)handle->data; Local<Value> argv[1] = { Number::New(isolate, data->pData_) }; Local<Function>::New(isolate, *(data->callback_))->Call(isolate->GetCurrentContext()->Global(), 1, argv); delete data; }
MyObject::MyObject(double value) : value_(value) { uv_async_init(uv_default_loop(), &on_play_record_end_callback_, UV_Async_Handler); }
MyObject::~MyObject() { printf(“nihao”); }
void MyObject::Init(Handle<Object> exports) { Isolate* isolate = Isolate::GetCurrent();
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
constructor.Reset(isolate, tpl->GetFunction());
exports->Set(String::NewFromUtf8(isolate, "MyObject"),
tpl->GetFunction());
}
void MyObject::New(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate);
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
args.GetReturnValue().Set(args.This());
}
else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
Local<Function> cons = Local<Function>::New(isolate, constructor);
args.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
void OnDataStreamPublish(MyObject* p) { while (true) { PT_ST_SNDUTIL_DATA data = new ST_SNDUTIL_DATA(); assert(p->value_ == 11); data->pData_ = p->value_; data->callback_ = &OnPlayRecordEnd; on_play_record_end_callback_.data = (void*)data; uv_async_send(&on_play_record_end_callback_); Sleep(100); } }
void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate);
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
obj->value_ += 1;
OnPlayRecordEnd.Reset(isolate, args[0].As<Function>());
HANDLE m_pThreadHandle = CreateThread(
NULL, // SD
0, // initial stack size
(LPTHREAD_START_ROUTINE)OnDataStreamPublish, // thread function
obj, // thread argument
0, // creation option
NULL // thread identifier
);
args.GetReturnValue().Set(Number::New(isolate, obj->value_));
}
// myobject.h #ifndef MYOBJECT_H #define MYOBJECT_H
#include <node.h> #include <node_object_wrap.h> #include <uv/uv.h>
class MyObject : public node::ObjectWrap { public: static void Init(v8::Handlev8::Object exports); double value_;
private: explicit MyObject(double value = 0); ~MyObject();
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
};
#endif
// addon.cc #include <node.h> #include “myobject.h”
using namespace v8;
void InitAll(Handle<Object> exports) { MyObject::Init(exports); }
NODE_MODULE(addon, InitAll)
// test.js var addon = require(’./MyObject’); var obj = new addon.MyObject(10); var i = 0; obj.plusOne(function (result) { i += 1; console.log(i + “:” + result);});
没看懂, 异步不正常? 会不会是UV_Async_Handler 这个函数的问题?
@wewea 异步是正常的,初步定为应该是处在UV_Async_Handler这个方法里面,现象就是大概执行了6-700多次异步回调之后,MyObject这个对象就被析构了,不知道是什么原因导致的。如果把Local<Function>::New(isolate, *(data->callback_))->Call(isolate->GetCurrentContext()->Global(), 1, argv);这句话注释了就不会出现了。现在就搞不明白是什么原因导致的,能麻烦帮我稍微看看,给个方向也行!谢谢了
现在发现把test.js回调里面的console.log(i + “:” + result);注释了就不出问题了,加上就不行,请问这是为什么呢?