gSoap中适当的内存控制



我目前正在使用 gSoap 库开发应用程序,并且对正确的用法库有一些误解。我生成了代理对象(-j 标志),它包装了我自己的类,如下所示。应用程序必须 24/7 全天候工作并同时连接到许多摄像机(~50 个摄像机),因此在每次请求后,我都需要清除所有临时数据。在每次请求后调用 soap_destroy() 和 soap_end() 是正常用法吗?因为每次请求后这样做似乎有点过分了。可能存在另一种正确使用的选项?

DeviceBindingProxy::destroy()
{
soap_destroy(this->soap);
soap_end(this->soap);
}
class OnvifDeviceService : public Domain::IDeviceService
{
public:
OnvifDeviceService()
: m_deviceProxy(new DeviceBindingProxy) 
{ 
soap_register_plugin(m_deviceProxy->soap, soap_wsse);
}
int OnvifDeviceService::getDeviceInformation(const Access::Domain::Endpoint &endpoint, Domain::DeviceInformation *information)
{
_tds__GetDeviceInformation tds__GetDeviceInformation;
_tds__GetDeviceInformationResponse tds__GetDeviceInformationResponse;
setupUserPasswordToProxy(endpoint);
m_deviceProxy->soap_endpoint = endpoint.endpoint().c_str();
int result = m_deviceProxy->GetDeviceInformation(&tds__GetDeviceInformation, tds__GetDeviceInformationResponse);
m_deviceProxy->soap_endpoint = NULL;
if (result != SOAP_OK) {
Common::Infrastructure::printSoapError("Fail to get device information.", m_deviceProxy->soap);
m_deviceProxy->destroy();
return -1;
}
*information = Domain::DeviceInformation(tds__GetDeviceInformationResponse.Manufacturer,
tds__GetDeviceInformationResponse.Model,
tds__GetDeviceInformationResponse.FirmwareVersion);
m_deviceProxy->destroy();
return 0;
}
}

要确保正确分配和取消分配托管数据,请执行以下操作:

soap_destroy(soap);
soap_end(soap);

您希望经常执行此操作,以避免内存被旧数据填满。这些调用将删除所有反序列化数据以及使用 soap_new_X() 和 soap_malloc() 函数分配的数据。

所有托管分配都将被删除,后跟soap_destroy()后跟soap_end()。之后,您可以再次开始分配并再次删除,依此类推。

分配托管数据:

SomeClass *obj = soap_new_SomeClass(soap);

可以使用soap_malloc进行原始托管分配,或者分配指针数组或 C 字符串:

const char *s = soap_malloc(soap, 100);

请记住,malloc 在C++并不安全。更好的是分配 std::string:

std::string *s = soap_new_std__string(soap);

数组可以用第二个参数分配,例如一个包含 10 个字符串的数组:

std::string *s = soap_new_std__string(soap, 10);

如果要保留通过这些调用删除的数据,请使用:

soap_unlink(soap, obj);

现在obj可以稍后使用delete obj删除。但请注意,obj中指向托管数据的所有指针成员在soap_destroy()soap_end()之后都已失效。因此,您可能必须在这些成员上调用soap_unlink(),否则可能会悬而未决。

gSOAP 的一个新酷功能是自动生成任何数据结构的深度复制和删除函数,从而节省了大量的编码时间:

SomeClass *otherobj = soap_dup_SomeClass(NULL, obj);

这会将obj复制到非托管堆空间。这是一个深层副本,用于检查对象图中的周期并删除此类周期以避免删除问题。还可以通过将soap而不是 NULL 作为soap_dup_SomeClass的第一个参数,将整个(循环)托管对象复制到另一个上下文。

要深度删除:

soap_del_SomeClass(obj);

这将删除obj,还会删除其成员指向的数据,依此类推。

要使用soap_dup_Xsoap_del_X函数,请使用 soapcpp2 分别带有选项-Ec-Ed

原则上,静态和堆栈分配的数据也可以序列化。但请考虑改用托管堆。

有关更多详细信息和示例,请参阅 https://www.genivia.com/doc/databinding/html/index.html#memory2。

希望这有帮助。

GSoap 文档的第 9.3 节中描述了必须处理内存的方式。

最新更新