我目前正在使用gSoap库开发应用程序,并对正确的使用库有一些误解。我已经生成了包含我自己的类的代理对象(-j标志),如下所示。应用程序必须全天候工作并同时连接到许多摄像机(~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;
}
}
答案 0 :(得分:1)
确保妥善分配和取消分配托管数据:
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 :: stringstd::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_X
和soap_del_X
函数,请分别使用soapcpp2选项-Ec
和-Ed
。
原则上,静态和堆栈分配的数据也可以序列化。但请考虑使用托管堆。
有关详细信息和示例,请参阅https://www.genivia.com/doc/databinding/html/index.html#memory2。
希望这有帮助。
答案 1 :(得分:0)
Section 9.3 of the GSoap documentation中描述了必须处理内存的方式。