C ++ - gsoap: параметры, передающие проблемы управления памятью - PullRequest
3 голосов
/ 22 декабря 2008

Я пишу для него веб-сервер и клиентскую тестовую заглушку. У меня есть вопросы, касающиеся управления параметрами памяти.

С моего клиента я вызываю функцию мыла ns1_func1 (вход * pInput, выход * pOutput) Теперь и входной, и выходной класс содержат указатели на другие структуры.

Например,

Выходной класс { класс abc * p1; класс def * p2; };

Мой вопрос - кто отвечает за распределение памяти? Отвечает ли клиент за распределение входной памяти, а сервер - за управление выходной памятью?

Прямо сейчас мой клиентский код выглядит примерно так

client_fn()
{

 ...

 input inp1;
 output * pOutput = NULL;
 ns1_func1(&inp1, pOutput);
 if(pOutput == NULL)
 {
   cout<<"pOut is NULL\n";
   return ERR;
 }
 else
 {
   // retrive output values from pOutput
 }

 ...
}

Я всегда получаю pOutput как NULL после вызова ns1_func1, несмотря на выделение pOutput с сервера с использованием soap_new_Output (soap, -1).

Кроме того, я понимаю, что мы должны использовать soap_new_X для выделения памяти, которая автоматически освобождается при вызове soap_destroy. Пожалуйста поправьте меня, если я ошибаюсь.

По сути, я борюсь, не зная, кто должен позаботиться о распределении / освобождении памяти в таких случаях.

Любая помощь будет отличной.

Ответы [ 4 ]

1 голос
/ 23 декабря 2008

Поскольку клиент и сервер - это, как правило, разные процессы или разные машины, каждый из них отвечает за собственное управление памятью. Клиент должен выделить память для своих входных параметров, которые затем gsoap сериализует для отправки на сервер.

Сервер десериализует входные параметры, выделяя любую память, необходимую для этого. Он распределяет память для своего вывода, который gsoap сериализует для отправки обратно клиенту. Клиент десериализует ответ сервера, выделяя всю необходимую ему память.

Вам определенно нужно использовать soap_malloc (et al) для выделения памяти, это единственный способ, которым библиотеки gsoap могут отследить, что необходимо освободить после очистки вызова SOAP.

В приведенном вами конкретном примере ns1_func1 сервер выделяет ответ, а сгенерированный клиентский код должен выделять любую необходимую ему память. Возможно, в WSDL что-то не так для этого вызова, что генерируемый код клиента не тот, который вы ожидаете.

0 голосов
/ 28 октября 2009

После выполнения этого кода:

output * pOutput = NULL;
ns1_func1(&inp1, pOutput);

pOutput будет всегда иметь значение NULL, независимо от того, что делает ns1_func. Вы передаете значение pOutput функции, которая в этом случае равна NULL. Функция не может изменить это значение, не зная адрес pOutput (записывается как & pOutput).

ns1_func1 запрашивает указатель на структуру «output», потому что именно там он хочет записать выходные данные. Это означает, что вам нужно выделить это пространство либо в стеке:

output theOutput;
output * pOutput = &theOutput;
ns1_func1(&inp1, pOutput);

или в кучу:

output * pOutput = malloc(sizeof(output));
ns1_func1(&inp1, pOutput);
...
free(pOutput);

Если бы ns1_func1 собирался выделить память для вас, он должен был бы вернуть указатель на выходную структуру. Для этого необходимо запросить адрес этого указателя или указатель на указатель. Другими словами, объявление типа:

output * pOutput = NULL;
different_ns1_func1(&inp1, &pOutput);
if (pOutput != NULL) {
    ...
    free(pOutput);
}

Извините, если это немного сбивает с толку, со всеми разговорами об указателях на указатели, но основной ответ на ваш вопрос заключается в том, что вы должны выделить память для функции для записи, потому что функция запрашивая адрес данных , а НЕ адрес указателя на данные .

0 голосов
/ 05 января 2009

Что такое подпись ns1_func1? Это ns1_func1 (вход *, выход *) или ns1_func1 (вход *, выход * и)? В первом случае вы никогда не сможете получить ненулевое значение.

0 голосов
/ 28 декабря 2008

Спасибо, Дентон,

Проблема, с которой я сталкиваюсь, заключается в том, что на сервере я выделяю память для классов abc и def, используя soap_new_abc и soap_new_def. Они не освобождаются во время очистки. В разделе очистки я вызываю soap_destroy, soap_end и soap_free. Согласно документации gsoap, soap_free должен вызывать ~ классы, выделенные через soap_new_X, но этого не происходит. Я на самом деле помещаю операторы DEBUG в ctors и ~ tors в soapC.cpp. Появляются операторы DEBUG в ctor, но не те, что содержатся в. Поэтому я боюсь, что могут быть утечки памяти.

Разве soap_delete_X не должен вызываться автоматически при очистке от soap_free?

...