1

我将 a 传递Napi::Promise::Deferred给 AsyncWorker,然后调用Promise::Defered.Resolve()AynscWork.OnOK。但是当我调用 Resolve() 时它总是崩溃


// node addon function 

Napi::Promise FileMd5Async(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    auto filePath = info[0].As<Napi::String>().Utf8Value();
    Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
    HashAsyncWorker *hashAsyncWorker = new HashAsyncWorker(env, deferred, filePath);
    hashAsyncWorker->Queue();
    return deferred.Promise();
}

// HashAsyncWorker.h
#pragma once
#include "third_party/node-addon-api/napi.h"

class HashAsyncWorker : public Napi::AsyncWorker {
    
    public:
        HashAsyncWorker(Napi::Env &env, Napi::Promise::Deferred& deferred, std::string filePath);
        ~HashAsyncWorker() override {};

        void Execute() override;
        void OnOK() override;
        void OnError(Napi::Error const &error) override;

    private:
        Napi::Env &env;
        Napi::Promise::Deferred& deferred;
        std::string filePath;
        std::string hashResult;
};

// // HashAsyncWorker.cc
#include "HashAsyncWorker.H"
#include "hash_utils.h"

HashAsyncWorker::HashAsyncWorker(Napi::Env &env, Napi::Promise::Deferred& deferred, std::string filePath) : Napi::AsyncWorker(env), env(env), deferred(deferred), filePath(filePath), hashResult("") {

}

void HashAsyncWorker::Execute() {
    hashResult = hash_utils::FileMd5(filePath);
}

void HashAsyncWorker::OnOK() {
    // crash here  
    //[1]    37056 segmentation fault  
    deferred.Resolve(Napi::String::New(Env(), hashResult)); 
}

void HashAsyncWorker::OnError(Napi::Error const &error) {
    deferred.Reject(error.Value());
}


4

1 回答 1

1

正确的。它崩溃是因为在堆上创建并被 node-addon-api 进一步使用的时间超过了在函数堆栈上创建HashAsyncWorker的对象。DeferredFileMd5Async

为了防止崩溃,您需要确保deferred生命周期足够长,以便onOK函数访问有效值。

事实上,N-API 对象,如napi_value,napi_deferred等(其中 node-addon-api 是一个瘦包装器)是指针,这意味着它们可以自由复制。

这样,如果您只是删除用于传递的引用deferred,您将防止发生崩溃。

删除构造函数声明、实现和字段声明中的三个 & 符号就足够了:

// HashAsyncWorker.h
#pragma once
#include "third_party/node-addon-api/napi.h"

class HashAsyncWorker : public Napi::AsyncWorker {
    
    public:
        HashAsyncWorker(Napi::Env &env, Napi::Promise::Deferred deferred, std::string filePath);
        ~HashAsyncWorker() override {};

        void Execute() override;
        void OnOK() override;
        void OnError(Napi::Error const &error) override;

    private:
        Napi::Env &env;
        Napi::Promise::Deferred deferred;
        std::string filePath;
        std::string hashResult;
};

// // HashAsyncWorker.cc
#include "HashAsyncWorker.H"
#include "hash_utils.h"

HashAsyncWorker::HashAsyncWorker(Napi::Env &env, Napi::Promise::Deferred deferred, std::string filePath) : Napi::AsyncWorker(env), env(env), deferred(deferred), filePath(filePath), hashResult("") {

}
于 2021-10-02T17:10:35.463 回答