2012-07-16 78 views
3

背景:我正在尝试创建一个用于演示目的和学习练习的node.js副本。v8关于对象生命周期的困惑

我试图调用一个回调函数时遇到了段错误我已经附加到了javascript中的一个对象。我使用obj->Set(xxx, callback)将值分配给对象。每当有一个http请求发生时,我会回到那个对象并使用obj->Get(xxx)来获得该回调并尝试调用它。但是,我在使用指针时遇到段错误。

下面的代码:

#include "HttpWrap.h" 
#include <cstdlib> 
#include "v8/include/v8.h" 
#include "libuv/include/uv.h" 

using namespace v8; 

HttpWrap::HttpWrap(const Arguments& args) 
{ 
    Local<ObjectTemplate> serverTemplate = ObjectTemplate::New(); 
    serverTemplate->SetInternalFieldCount(1); 
    serverTemplate->Set(String::New("listen"), FunctionTemplate::New(Listen)); 

    Local<Object> localServer = serverTemplate->NewInstance(); 
    localServer->SetInternalField(0, External::New(this)); 

    String::AsciiValue ip_address(args[0]); 
    int port = args[1]->Int32Value(); 

    handle = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); 
    uv_tcp_init(uv_default_loop(), handle); 
    handle->data = this; 
    uv_tcp_bind(handle, uv_ip4_addr(*ip_address, port)); 

    server = Persistent<Object>::New(localServer); 
} 

Handle<Value> HttpWrap::Listen(const Arguments& args) 
{ 
    puts("HttpWrap::Listen"); 

    HandleScope scope; 

    Local<External> wrap = Local<External>::Cast(args.Holder()->GetInternalField(0)); 
    HttpWrap* httpWrap = static_cast<HttpWrap*>(wrap->Value()); 
    httpWrap->server->Set(String::New("onrequest"), args[0]); 
    uv_listen((uv_stream_t*) httpWrap->handle, 128, OnConnection); 

    return scope.Close(Undefined()); 
} 

void HttpWrap::OnConnection(uv_stream_t* handle, int status) 
{ 
    puts("HttpWrap::OnConnection"); 
    uv_tcp_t* client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); 
    uv_tcp_init(uv_default_loop(), client); 
    client->data = handle->data; 
    uv_accept(handle, (uv_stream_t*) client); 
    uv_read_start((uv_stream_t*) client, AllocConnection, OnRead); 
} 

uv_buf_t HttpWrap::AllocConnection(uv_handle_t* handle, size_t suggested_size) 
{ 
    puts("HttpWrap::AllocConnection"); 
    return uv_buf_init((char*) malloc(suggested_size), suggested_size); 
} 

void HttpWrap::OnRead(uv_stream_t* server, ssize_t nread, uv_buf_t buf) 
{ 
    HandleScope scope; 
    puts("HttpWrap::OnRead"); 

    HttpWrap* httpWrap = static_cast<HttpWrap*>(server->data); 
    Local<String> callbackSym = String::New("onrequest"); 
    Local<Value> value = httpWrap->server->Get(callbackSym); 

    if (!value->IsFunction()) 
    { 
     puts("Value is not a function"); 
    } 
    else 
    { 
     puts("Value is a function"); 
     Local<Function> callback = Local<Function>::Cast(value); 
     Local<Value>* argv = new Local<Value>[1]; 
     argv[0] = String::New("test"); 
     puts("Invoking callback"); 
     callback->Call(Context::GetCurrent()->Global(), 1, argv); 
     puts("invoked callback"); 
    } 

    free(buf.base); 
    uv_close((uv_handle_t*) server, OnClose); 
} 

void HttpWrap::OnClose(uv_handle_t* handle) 
{ 
    puts("HttpWrap::OnClose"); 
} 

available on Github

感兴趣的行是36和65.每当尝试调用callback->Call时,就会发生段错误。

建议的任何想法或良好的做法非常感谢!

回答

1

不幸的是,当解决这个问题时,我得到了一个小小的隧道视野。主要的问题是我在尝试调用回调之前正在处理主要上下文。由于上下文尝试调用js空间中的代码失败。

+1

当您遇到崩溃并在调试器中检查它时,请始终检查潜在的指针以及它们指向的结构以查看它们是否有效。在例如GDB就像'print callback','print * callback'和'print callback-> Call'。 – 2012-07-16 05:47:58