AsyncWorker.OnOK中调用Promise::Deferred.Resolve()触发崩溃如何解决
问题根因
FileMd5Async函数中声明的Napi::Promise::Deferred deferred是栈上局部变量,函数执行结束返回Promise后,该栈变量会被销毁。HashAsyncWorker类中存储的是deferred的左值引用,OnOK回调触发时访问的是已经被释放的内存地址,直接触发段错误。
修复方案
- 将HashAsyncWorker的
deferred成员变量从引用类型改为值类型。Napi公开的所有值类型本质都是V8对象的句柄,拷贝操作仅增加句柄引用计数,开销极低,且会保证内部关联的Promise对象不会被提前回收。 - 可删除自定义的
env成员变量,Napi::AsyncWorker基类已经提供Env()方法可直接获取当前环境对象,避免重复持有引用带来的额外风险。
修改后的代码示例
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::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), deferred(std::move(deferred)), filePath(filePath), hashResult("") { } // Execute、OnOK、OnError方法无需修改 void HashAsyncWorker::Execute() { hashResult = hash_utils::FileMd5(filePath); } void HashAsyncWorker::OnOK() { deferred.Resolve(Napi::String::New(Env(), hashResult)); } void HashAsyncWorker::OnError(Napi::Error const &error) { deferred.Reject(error.Value()); }
原FileMd5Async函数的逻辑无需任何调整。
内容的提问来源于stack exchange,提问作者QuinnChen
相关产品推荐
相关产品推荐

