Правильный контроль памяти в 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;
    }

}

2 ответа

Чтобы обеспечить правильное распределение и освобождение управляемых данных:

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_X а также soap_del_X функции используют soapcpp2 с опциями -Ec а также -Edсоответственно.

В принципе, статические данные и данные, размещенные в стеке, также могут быть сериализованы. Но вместо этого рассмотрите возможность использования управляемой кучи.

См. https://www.genivia.com/doc/databinding/html/index.html для получения дополнительной информации и примеров.

Надеюсь это поможет.

Способ обращения с памятью описан в разделе 9.3 документации GSoap.

Другие вопросы по тегам