【发布时间】:2019-11-09 14:12:26
【问题描述】:
好的,首先我对 C++ 很陌生,所以如果我的理解很差,我深表歉意。我会尽力解释自己。我所拥有的是我正在使用一个返回 std::shared_ptr<SomeObject> 的库函数,然后我有一个不同的库函数,它采用原始指针参数(更具体地说是 node-addon-api Napi::External<T>::New(Napi::Env env, T *data) 静态函数)。我想使用我的 std::shared_ptr 创建一个Napi::External 对象。我目前正在做的是这样的:
{
// ...
std::shared_ptr<SomeObject> pSomeObject = something.CreateSomeObject();
auto ext = Napi::External<SomeObject>::New(info.Env(), pSomeObject.get());
auto instance = MyNapiObjectWrapper::Create({ ext });
return instance;
}
但我担心这会遇到内存问题。 我的 pSomeObject 只存在于当前范围内,所以我想在返回之后应该发生什么,它的引用计数将下降到 0 并且它指向的 SomeObject 实例将被销毁,因此我会遇到我返回的实例的问题使用这个对象。但是我已经能够从我的实例中运行此代码并在 SomeObject 上调用函数,所以我想我的理解可能是错误的。
我的问题是当给定一个共享指针但由于其他第三方库的要求我需要处理一个原始指针时我应该怎么做?向我提出的一个选项是制作对象的深层副本并创建指向该对象的指针
如果我对此的理解有误,请纠正我,因为我说过我对 C++ 很陌生。
=============================
编辑:
所以我的原始帖子信息中缺少有关所有权以及该块到底是什么的信息。该块是我对Napi::ObjectWrap 实例的实现的实例方法。这个实例方法需要返回一个Napi::Object,它可以在node.js中被调用者使用。我正在使用Napi::External,因为我需要在创建返回的Napi:Object 时将Napi::Value 的子类型传递给构造函数New 函数,并且我需要在我提取的外部包装SomeObject 对象我的MyNapiObjectWrapper 构造函数是这样的:
class MyNapiObjectWrapper
{
private:
SomeObject* someObject;
static Napi::FunctionReference constructor; // ignore for now
public:
static void Init(Napi::Env env) {...}
MyNapiObjectWrapper(const CallbackInfo& info)
{
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
// My original code to match the above example
this->someObject = info[0].As<const Napi::External<SomeObject>>().Data();
}
DoSomething()
{
this->someObject->DoSomething();
}
}
从那以后我意识到我可以在创建外部时传递共享指针的地址并按如下方式使用它
// modified first sample
{{
// ...
std::shared_ptr<SomeObject> pSomeObject = something.CreateSomeObject();
auto ext = Napi::External<SomeObject>::New(info.Env(), &pSomeObject);
auto instance = MyNapiObjectWrapper::Create({ ext });
return instance;
}
// modified second sample
class MyNapiObjectWrapper
{
private:
std::shared_ptr<SomeObject> someObject;
static Napi::FunctionReference constructor; // ignore for now
public:
static void Init(Napi::Env env) {...}
MyNapiObjectWrapper(const CallbackInfo& info)
{
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
// My original code to match the above example
this->someObject =
*info[0].As<const Napi::External<std::shared_ptr<SomeObject>>>().Data();
}
DoSomething()
{
this->someObject->DoSomething();
}
}
所以现在我传递一个指向 shared_ptr 的指针来创建我的Napi::External,我现在的问题是这样可以吗?就像我在开始时所说的那样,我是 C++ 新手,但这似乎有点异味。但是我通过一些调试对其进行了测试,并且可以看到引用计数上升,所以我想我很清楚???
【问题讨论】:
-
如果不查看您没有/不能包含的代码,我们就无法知道对象的所有权。显然,
pSomeObject的对象所有者在块的末尾被销毁。如果调用的任何方法都没有预料到,那么您将拥有 UB。但是,如果他们深复制pSomeObject指向的对象,一切都会好的。它是阅读文档时间寻找所有权信息。 -
我不确定
CreateSomeObject函数中发生了什么,它们必须保持对象的所有权,因为 SomeObject 实例在块之后没有被销毁。最后发生的事情是我创建了External来包装一些对象,然后我将外部传递给Napi::ObjectWrapper(在上面的示例中为MyNapiObjectWrapper),因此我可以提取指针并将其保留为成员变量。我可以看到为什么我的代码是错误的,但我还看不出我应该如何修复它。
标签: c++ memory-management shared-ptr smart-pointers node-addon-api