views:

1068

answers:

4

I am writing a web server and client test stub for it. I have questions regarding memory management of the parameters.

From my client I am calling a soap function ns1_func1(input * pInput, output* pOutput) Now both input and output class contain pointers to other structs.

For e.g

class Output { class abc * p1; class def * p2; };

My question is - who is responsible for memory allocations? Is client responsible for input memory allocations and server responsible for output memory management?

Right now my client code looks somthing like this

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
 }

 ...
}

I am always getting pOutput as NULL after call to ns1_func1 in spite of allocating pOutput from the server using soap_new_Output(soap, -1).

Also, my understanding is that we should use soap_new_X to allocate memory which gets automatically deallocated when we call soap_destroy. Pls correct me if I am wrong.

Basically I am struggling with no knowledge about who is supposed to take care of memory allocation/deallocation in such cases.

Any help would be great.

+1  A: 

Because the client and server are generally different processes, or different machines, they are each responsible for their own memory management. The client must allocate the memory for its input parameters, which gsoap then serializes to send to the server.

The server deserializes the input parameters, allocating any memory it needs to do so. It allocates the memory for its output, which gsoap serializes to send back to the client. The client deserializes the server's response, allocate any memory it needs to do so.

You definitely need to use soap_malloc (et al) for memory allocations, thats the only way the gsoap libraries can track what needs to be freed when the SOAP call cleans up.

In the specific ns1_func1 example you gave, the server allocates the response and the generated client code is supposed to allocate any memory it requires. There may be something wrong in the WSDL for that call, that the client code being generated is not what you expect.

DGentry
A: 

Thanks Denton,

The problem I am facing is that in the server, I allocate memory for classes abc and def using soap_new_abc and soap_new_def. These are not freed during clean up. In clean up section, I am calling soap_destroy, soap_end and soap_free. As per gsoap documentation, soap_free should call the ~tors of classes allocated through soap_new_X but thats not happening. I actually put DEBUG statements in the ctors and ~tors in soapC.cpp. The DEBUG statements in ctor are appearing but not those in ~tors. So I fear there may be memory leaks.

Isnt soap_delete_X supposed to be called automatically during clean up from soap_free?

A: 

What is the signature of ns1_func1? Is it ns1_func1( Input*, Output*) or ns1_func1( Input*, Output*& ) ? For the first case you would never be able to get a non-null value.

sachin
A: 

After executing this code:

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

pOutput will always be NULL, no matter what ns1_func does. You are passing the value of pOutput to the function, which in this case is NULL. The function has no way to change that value without knowing the address of pOutput (written as &pOutput).

ns1_func1 asks for a pointer to an "output" struct because that's where it wants to write the output data. So that means you need to allocate that space, either on the stack:

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

or on the heap:

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

If ns1_func1 was going to allocate the memory for you, it would have to return a pointer to the output struct. To do that, it would need to ask for the address of that pointer, or a pointer to a pointer. In other words, a declaration like:

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

Sorry if this is a little confusing, with all the talk of pointers to pointers, but the basic answer to your question is that you must allocate the memory for the function to write to because the function is asking for the address of the data and NOT the address of a pointer to the data.

benzado