"node-addon-api" 中的某些 API 是否存在 "undefined behavior" 问题?
Is there an "undefined behavior" problem with some APIs in "node-addon-api"?
在<napi.h>
中,classPropertyDescriptor
.
中的静态方法Accessor
有一些重载声明
其中一个重载声明是 here:
template <typename Getter>
static PropertyDescriptor Accessor(Napi::Env env,
Napi::Object object,
const std::string& utf8name,
Getter getter,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
该声明需要对 const std::string
的引用
该声明的定义在 <napi-inl.h>:
template <typename Getter>
inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
Napi::Object object,
const std::string& utf8name,
Getter getter,
napi_property_attributes attributes,
void* data) {
return Accessor(env, object, utf8name.c_str(), getter, attributes, data);
}
如您所见,该实现采用传递的 std::string
的 .c_str()
,因为该实现实际上使用了另一个需要 const char*
.
的重载
使用的重载也在<napi-inl.h>
:
template <typename Getter>
inline PropertyDescriptor
PropertyDescriptor::Accessor(Napi::Env env,
Napi::Object object,
const char* utf8name,
Getter getter,
napi_property_attributes attributes,
void* data) {
using CbData = details::CallbackData<Getter, Napi::Value>;
auto callbackData = new CbData({ getter, data });
napi_status status = AttachData(env, object, callbackData);
if (status != napi_ok) {
delete callbackData;
NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
}
return PropertyDescriptor({
utf8name,
nullptr,
nullptr,
CbData::Wrapper,
nullptr,
nullptr,
attributes,
callbackData
});
}
该实现使用 Node-API,因为 node-addon-api
只是 Node-API 的 C++ 包装器。事实是,从.c_str()
得到的const char* utf8name
原样传递给构造函数,并存储在私有成员napi_property_descriptor _desc;
结论:每次你使用 Napi::PropertyDescriptor::Accessor
传递一个 std::string 然后将 PD 存储在一个向量中,或者只是让字符串超出范围而 PD 仍然在这里,你触发一个未定义的行为!
示例:
Napi::Object TheNewObject = Napi::Object::New(env);
std::vector<Napi::PropertyDescriptor> vProps;
for (size_t index = 0; index < 2; ++index ) {
std::string strName("MyName_");
strName += std::to_string(index);
auto PD = Napi::PropertyDescriptor::Accessor(env, TheNewObject, strName, Caller);
vProps.push_back(PD);
}
我在 12 天前打开了一个问题 here,但没有用。
编辑:阅读评论后,我应该补充一点:
napi_property_descriptor
是一个简单的C结构。
- 该结构的地址稍后将传递给节点-API
napi_define_properties
PropertyDescriptor
的当前实施确实存在问题。
参见 https://github.com/nodejs/node-addon-api/issues/1127#issuecomment-1036394322
很高兴我没有完全精神错乱。
在<napi.h>
中,classPropertyDescriptor
.
Accessor
有一些重载声明
其中一个重载声明是 here:
template <typename Getter>
static PropertyDescriptor Accessor(Napi::Env env,
Napi::Object object,
const std::string& utf8name,
Getter getter,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
该声明需要对 const std::string
该声明的定义在 <napi-inl.h>:
template <typename Getter>
inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
Napi::Object object,
const std::string& utf8name,
Getter getter,
napi_property_attributes attributes,
void* data) {
return Accessor(env, object, utf8name.c_str(), getter, attributes, data);
}
如您所见,该实现采用传递的 std::string
的 .c_str()
,因为该实现实际上使用了另一个需要 const char*
.
使用的重载也在<napi-inl.h>
:
template <typename Getter>
inline PropertyDescriptor
PropertyDescriptor::Accessor(Napi::Env env,
Napi::Object object,
const char* utf8name,
Getter getter,
napi_property_attributes attributes,
void* data) {
using CbData = details::CallbackData<Getter, Napi::Value>;
auto callbackData = new CbData({ getter, data });
napi_status status = AttachData(env, object, callbackData);
if (status != napi_ok) {
delete callbackData;
NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
}
return PropertyDescriptor({
utf8name,
nullptr,
nullptr,
CbData::Wrapper,
nullptr,
nullptr,
attributes,
callbackData
});
}
该实现使用 Node-API,因为 node-addon-api
只是 Node-API 的 C++ 包装器。事实是,从.c_str()
得到的const char* utf8name
原样传递给构造函数,并存储在私有成员napi_property_descriptor _desc;
结论:每次你使用 Napi::PropertyDescriptor::Accessor
传递一个 std::string 然后将 PD 存储在一个向量中,或者只是让字符串超出范围而 PD 仍然在这里,你触发一个未定义的行为!
示例:
Napi::Object TheNewObject = Napi::Object::New(env);
std::vector<Napi::PropertyDescriptor> vProps;
for (size_t index = 0; index < 2; ++index ) {
std::string strName("MyName_");
strName += std::to_string(index);
auto PD = Napi::PropertyDescriptor::Accessor(env, TheNewObject, strName, Caller);
vProps.push_back(PD);
}
我在 12 天前打开了一个问题 here,但没有用。
编辑:阅读评论后,我应该补充一点:
napi_property_descriptor
是一个简单的C结构。- 该结构的地址稍后将传递给节点-API
napi_define_properties
PropertyDescriptor
的当前实施确实存在问题。
参见 https://github.com/nodejs/node-addon-api/issues/1127#issuecomment-1036394322
很高兴我没有完全精神错乱。