BACK TO MAIN PAGE
 

gSOAP FAQ

Why is it that I cannot deserialize polymorphic objects in my C service?
Services developed in C++ with gSOAP support full polymorphism, including xsd:anyType. However, the C language limitations make it more difficult to map schema complexType extensions to C structs. Therefore, you should consider writing your Web services app in C++ to support polymorphic types. In order to support polymorphism in C, we suggest to use advanced features such as the int __type; void* construct to serialize a pointer to an object of type X. This is done by setting __type = SOAP_TYPE_X and the void* pointer to the object (see documentation). Obviously, the deserializer automatially sets __type and void* according to the XML content and its xsi:type value which is required. When xsi:type values are not provided, such as for the base case of an XSD extension/restriction, you should match the content according to the element tag name by defining a type (struct or typedef) with the element name.
I get a "No deserializer found to deserialize a '...' using encoding style 'http://schemas.xmlsoap.org/soap/encoding/'" error from an Axis server. What is the problem?
Some toolkits, including Axis, require typed SOAP RPC messages with xsi:type information for each accessor. Use soapcpp2 option -t to automatically re-generate serialization code to produce typed messages.
I suspect that gSOAP has a memory leak, because no memory is released when I check the malloc() behavior. Am I correct?
The gSOAP engine uses a memory management method to allocate and deallocate memory. The deallocation is performed with soap_destroy() followed by soap_end(). However, when you compile with -DDEBUG or -DSOAP_MEM_DEBUG then no memory is released until soap_done() is invoked. This ensures that the gSOAP engine can track all malloced data to verify leaks and double frees in debug mode. Use -DSOAP_DEBUG to use the normal debugging facilities without memory debugging. Note that some compilers have DEBUG enabled in the debug configuration, so this behavior should be expected unless you compile in release config.
What is the "Data corruption in dynamic allocation" error?
When your application uses soap_malloc() to allocate a (temporary) chunk of data and the allocated size is exceeded, the gSOAP engine will detect this buffer overrun in DEBUG mode. Check your code and/or enlarge the allocated buffer.
The C/C++ compiler I'm using produces an error for empty structs and/or classes that are present in the generated code. What should I do?
Use -DWITH_NOEMPTYSTRUCT as a C/C++ compiler option to add dummy members automatically to the generated code (gSOAP version 2.7.9g or higher). I downloaded a new release version to upgrade. However, I got a link error for one of more function calls in the code generated by soapcpp2.
You were probably using the platform-independent release earlier and upgraded with a platform-dependent release. The platform-independent release builds libgsoap, while the platform-dependent release assumes you will link stdsoap2.c/pp. Thus, you're using the old gSOAP engine with new code generated by soapcpp2.
How do I build a universal PPC/Intel binary for MAC OS?
To build a Mac OS X Universal Binary you have to run "automake --ignore-deps":
automake --ignore-deps && ./configure CFLAGS="-arch ppc -arch i386" LDFLAGS="-arch ppc -arch i386" && make clean && make
Why do I get a 'Compliance Warning'?
WS-I Basic Profile compliance warnings are meant to inform you about potential interoperability problems with other SOAP/XML Web services. The WS-I Basic Profile publication consists of a set of non-proprietary Web services specifications, along with clarifications and amendments to those specifications which promote interoperability. Compliance warnings for existing services should be ignored, because compliance requires changes to the service WSDL that would break other applications that depend on the service. You may consider these compliance issues for new services however, see the Basic Compliance Report we prepared for gSOAP.
What is the difference between qualified element/attribute forms and unqualified forms?
When a schema defines element forms to be qualified by default (elementFormDefault="qualified"), the header file includes a directive
//gsoap ns schema elementForm: qualified
Likewise, when the default is unqualified, you will find
//gsoap ns schema elementForm: unqualified
When an element form is qualified by default, elements in XML instances of the schema are required to be namespace qualified. Without going into too much detail, the XML basically looks like:
<x:foo xmlns:x="urn:foobar">
  <x:bar>bar is qualified</x:bar>
</x:foo>
or:
<foo xmlns="urn:foobar">
  <bar>bar is qualified</bar>
</foo>
When the element form is unqualified (as in SOAP RPC encoding), we would have:
<x:foo xmlns:x="urn:foobar">
  <bar>bar is unqualified</bar>
</x:foo>
Note that sometime we can have multiple namespaces as in:
<x:foo xmlns:x="urn:foo">
  <y:bar xmlns:y="urn:bar"></y:bar>
</x:foo>
or:
<x:foo xmlns:x="urn:foo" xmlns="urn:bar">
  <bar></bar>
</x:foo>
In the last example the bar element belongs to the "urn:bar" namespace, because the default namespace is "urn:bar". With Visual Studio .NET 2003 WSDL import, we could not successfully deserialize data from a multi-namespace situation when a response element contains an element of struct type in a second namespace. The individual members of the struct were ignored on the .NET side until the element form default 'qualified' was defined.
Tuning TCP/IP TIME_WAIT for systems with high connection rates
When a large number of connections in the TIME_WAIT state are observed, e.g. using the "netstat" command to monitor open TCP/IP connections, the system exhibits poor throughput possibly coupled with high CPU use.

The TIME_WAIT state is used to deal with possible problems related to unreliable or delayed packet delivery. TCP holds connections for a temporary waiting period (TIME_WAIT) to ensure that any delayed packets are caught and not treated as new connection requests. The size of TIME_WAIT is supposed to be twice the maximum segment lifetime or twice the time a packet can remain alive on a particular IP network. For some operating systems, this can be as high as 4 minutes. On busy systems, this can lead to a depleation of TCP port resources. Low throughput may occur due to many connections sitting in TIME_WAIT state.

The work-around is to reduce the operating system setting for TIME_WAIT substantially to the operating system minimum of 15 or 30 seconds (depending on OS).

  1. For Windows: Use regedit and create a REG_DWORD named TcpTimedWaitDelay under
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TcpIp\Parameters
    
    Set it to a decimal value of 30 which is for 30 seconds - the minimum.
  2. For AIX: To see the current TCP_TIMEWAIT value, run the following command:
    /usr/sbin/no a | grep tcp_timewait 
    
    To set the TCP_TIMEWAIT values to 15 seconds, run the following command:
    /usr/sbin/no o tcp_timewait =1 
    
    The tcp_timewait option is used to configure how long connections are kept in the timewait state. It is given in 15-second intervals, and the default is 1.
  3. For Linux: Set the timeout_timewait paramater using the following command:
    /sbin/sysctl -w net.ipv4.vs.timeout_timewait=30 
    
    This will set TME_WAIT for 30 seconds.
  4. For Solaris: Set the tcp_time_wait_interval to 30000 milliseconds as follows:
    /usr/sbin/ndd -set /dev/tcp tcp_time_wait_interval 30000
    
Why do I get a warning on a parameter with 'a type that does not correspond to the required unique type'?
SOAP RPC literal encoding requires the operation parameters to be described as top-level Schema elements in WSDL. Therefore, a service operation with parameter 'x' of type 'X' has an <element name="x" type="X"/> definition in the Schema of the service. A parameter 'x' of type 'Y' cannot be defined, since 'x' is already bound to type 'X'. If you must use SOAP RPC literal encoding, rename the parameter, e.g. 'y' of type 'Y', or define new schema namespaces by qualifying the parameter names, e.g. 'arg__x', 'arg__y', etc. You can use document literal encoding to avoid this problem, or SOAP RPC encoding (not WS Basic Profile compliant).
I get a link error in VC++. What should I do?
  • Change .c into .cpp extensions.
  • Link your application with soapC.cpp, soapClient.cpp (or soapServer.cpp for services), and stdsoap2.cpp.
  • Check the actual-formal parameter passing (soapStub.h contains the prototypes of the generated stub functions).
  • You need winsock.dll ("wsock32.lib"). To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" tab (the project file needs to be selected in the file view) and add "wsock32.lib" to the "Object/library modules" entry.
My code segfaults. What can I do?
  • Make sure that the gSOAP run-time environment (struct soap) is initialized by calling soap_init(&soap).
  • When working with C++ applications, make sure that you don't include the gSOAP header file directly in your C++ sources. You must use the gSOAP-generated soapH.h file instead, which includes the proper class extensions with virtual serialization methods.
  • Make sure you don't pass the gSOAP run-time environment (struct soap) by value to your application functions. Always pass struct soap by reference or pointer, just like the internal gSOAP functions do. In case you need to make a copy of it, use soap_copy().
  • Make sure all pointers that occur in the data structures that are passed as parameters to remote methods are initialized, i.e. pointers should be NULL or point to a valid object.
  • Make sure all class instances that are passed as parameters to remote methods are initialized, i.e. the virtual method tables (VMTs) must be set.
  • Make sure that no two (or more) threads access the same gSOAP run-time environment (struct soap) concurrently, i.e. use separate run-time environments in threads.
  • Remove all calls to soap_destroy() and soap_end() and rerun to check if the segfault results from gSOAP's garbage collect cleanup.
  • If the segfault occurs in the soap_destroy() cleanup, remove all deallocation calls in the class' destructors to avoid duplicate deallocations (one by the destructor and one by gSOAP's cleanup). Compensate the elimination of deallocation calls by allocating data solely with soap_malloc() and soap_new_Class() routines in your code. Alternatively, you can use soap_unlink() in the class destructors to unlink the data from gSOAP's deallocation chain before deallocating it in the class destructor (see the gSOAP documentation on soap_malloc(), soap_new_Class(), and soap_unlink() in class methods).
  • If the segfault occurs in the soap_end() cleanup, then it is likely that data is already deallocated with free() in your code and deallocated again in soap_end(). Use soap_unlink() to unlink the data from gSOAP's deallocation chain before freeing it up.
  • When you use OpenSSL and/or Zlib, please compile all sources with WITH_OPENSSL and/or WITH_GZIP to ensure that the soap struct's layout is identical in all places where it is used.
The time_t deserialization appears to be incorrect, because the time_t value is off by one or more hours. How can I fix this?
Some platforms do not support timegm() to convert time expressed in UCT to time_t values. Therefore, the gSOAP kernel uses gettimeofday() or ftime() with mktime() to deserialize xsd:dateTime values into time_t. As a result, when the timezone on the machine on which gSOAP runs is set incorrectly, this will cause the time_t value to be off by one or more hours. Unfortunately, the problem is more difficult with Solaris 8 and earlier, because Solaris does not implement the DST settings of gettimeofday() and ftime() correctly.
I wrote a Web Service that has a method that returns a data structure allocated on the stack. My service returns the wrong values and/or crashes. How can I allocate temporary data?
Use function:
void *soap_malloc(size_t n); // gSOAP 1.X
void *soap_malloc(struct soap *soap, size_t n); // gSOAP 2.X
These functions allocate memory on the heap that will be released upon calling soap_end() after soap_serve(). For example, in a gSOAP service:
main()
{ ...
  soap_serve(&soap);
  soap_end(&soap);
  ...
}
An example remote method that allocates a temporary string is:
int ns__itoa(struct soap *soap, int i, char **a)
{ *a = (char*)soap_malloc(soap, 11);
  sprintf(*a, "%d", i);
  return SOAP_OK;
}
Note that you don't want to use local function variables to store values such as strings, because the values are allocated on the stack and deallocated when the function returns while serialization of the values takes place after return. This allocation with soap_malloc() can also be used to allocate strings for the SOAP Fault data structure, for example:
int ns__mymethod(struct soap *soap, ...)
{ ...
  if (exception)
  { char *message = (char*)soap_malloc(soap, 1024);
    char *details = (char*)soap_malloc(soap, 1024);
    sprintf(message, ...);
    sprintf(details, ...);
    return soap_receiver_fault(soap, message, details);
  }
  ...
}
I get a tag mismatch error and/or data appears to be ignored when receiving SOAP/XML messages.
Check that your gSOAP header file includes //gsoap directives to define XML namespaces. These namespace bindings will be added to a .nsmap file generated by the gSOAP compiler (or you can write your own .nsmap file). The gSOAP header file requires a one-to-one correspondence between namespace prefix and the namespace name. Therefore, a namespace name may not occur more than once in a //gsoap ... service namespace directive.
My code appears to ignore data when receiving SOAP/XML messages. How can I detect unrecognized element tags at run time and let my application fault?
SOAP allows optional elements to be ignored. As a side effect, a namespace mismatch and/or tag name mismatch will result in dropping the element. If the namespace and/or tag name are defined correctly, data will never be dropped at run time. To assist debugging and to catch dropped elements, set the soap_set_imode(&soap, SOAP_XML_STRICT) flag. This will enforce strict validation of messages to catch (unknown elements and namespaces. Another way to control the dropping of unknown elements is to define the fignore callback. For example:
{ struct soap soap;
  soap_init(&soap);
  soap.fignore = mustmatch; // overwrite default callback
  ...
  soap_done(&soap);	// reset callbacks
}
int mustmatch(struct soap *soap, const char *tag)
{ return SOAP_TAG_MISMATCH;	// every tag must be handled
}
The tag parameter contains the offending tag name. You can also selectively return a fault:
int mustmatch(struct soap *soap, const char *tag)
{ if (soap_match_tag(soap, tag, "ns:login*"))	// all tags in namespace "ns" that start with "login" are optional
    return SOAP_OK;
  return SOAP_TAG_MISMATCH;	// every other tag must be understood (handled)
}
SOAP 1.1 allows the return parameter elements of a SOAP response to be 'anonymous'. How can I tell gSOAP to use anonymous return parameter names?
For gSOAP 2.1.11 and higher, specify the function prototype without parameter names. For earlier gSOAP releases, you can prefix the return parameter names with an underscore ('_'). For example:
int ns__mymethod(..., int *_return); // single anonymous output parameter
and
int ns__mymethod(..., struct ns__mymethodResponse{int _return1; char *_return2; ...} *result); // multiple output paramers
How can I tell gSOAP to ignore certain declarations of types in a header file so I can write class methods that use parameters of these types?
You can provide the type declarations in the header file and use the 'extern' qualifier or enclose the type declarations between [ and ] to make them 'transient', i.e. non-serializable. For example:
extern class ostream; // can't be (de)serialized so must be declared a transient type
class ns__foo
{ public:
  char *s;
  struct soap *soap; // special field: already transient
  ns__foo();
[ ns__foo(const char *t); // transient constructor
  print(ostream &s); // transient method
]
};
with e.g. the following implementation of ns__foo:
 
ns__foo::ns__foo(const char *t)
{ s = (char*)soap_malloc(soap, strlen(t)+1);
  strcpy(s, t);
}
The 'struct soap* soap' field in this class is a special field set by gSOAP's deserializers and the gSOAP-generated soap_new_ns__foo() function.
How can I tell gSOAP to use primitive XSD schema types or SOAP-ENC schema types?
Use typedef declarations for primitive types in the header file input to the compiler. This is important for SOAP RPC encoding style. For example, to declare a XSD schema string type, declare typedef char *xsd__string; and use the xsd__string type in remote method parameters and other compound data structures. See the documentation for more details on primitive XSD schema types and the section on doc/literal encoding. The declaration of SOAP-ENC schema types is similar. For example, typedef char *SOAP_ENC__string declares a SOAP-ENC:string schema type.
How do I debug a SOAP client?
Compile stdsoap2.cpp (or stdsoap2.c for C) with compiler option -DDEBUG (/DDEBUG in MSVC++) to enable the DEBUG macro. You can also uncomment "#define DEBUG" in stdsoap2.h and recompile stdsoap2.cpp/stdsoap2.c. When you run your application, three files are created in the current directory: SENT.log, RECV.log, and TEST.log. All output messages are appended to SENT.log, all input messages are appended to RECV.log, and TEST.log contains various logging messages generated by the gSOAP runtime environment. Alternatively, you can use the example plugin code provided in the distribution package in extras/plugin.h to develop an application that can selectively log input and output messages. In addition, you can use a simple trick to inspect a client request message by leaving the endpoint URL empty ("" string). This will send the request message to stdout. The client application expect the response to be available from stdin. So, unless you provide a response message using redirect e.g. from a file or a service application using Unix pipes, you will have to terminate the client application.
How do I debug a Web Service installed as a CGI application?
1. Uncomment "#define DEBUG" in stdsoap.h and recompile your Web Service application. Install the executable as a CGI application on your Web server. Create three empty files in the same directory: SENT.log, RECV.log, and TEST.log. They should have read and write permissions for "other" (i.e. for everyone). These files will log all accesses to the CGI application. Do not forget to remove them later and turn off debugging.
2. Alternatively, compile your Web Service application. Create a file with the SOAP request message and use file redirect to input this message as standard input to the executable, which should print the SOAP response message.
Does gSOAP support multi-threading?
Yes, gSOAP 2.x does. There are differences in the API's used in gSOAP 2.X compared to gSOAP 1.X to support multi-threading. Section 3 of the gSOAP 2.X documentation details these differences.
I wrote a client and service that exchange strings, but I get garbage or I get only one character communicated and not the entire string!?
Your function prototype is probably similar to "mymethod(char *in, char *out)". The output parameter "out" is a pointer to a byte instead of a pointer to a string (output parameters must be pointers or references to a type). The correct way to do this is: "mymethod(char *in, char **out)" or mymethod(char *in, char *&out)".
I wrote a client and service that exchange strings declared as char[N], but I get an array of N bytes in the payload!?
If you use a fixed-size array of chars, the array is (de)marshalled as an array of bytes and not a string. Always use char* for strings. gSOAP does not and will not support fixed-size string arrays because the actual data transmitted may not fit the array which can lead to data loss.
I wrote a remote method declaration and the compiler gives a syntax error for parameter names that are keywords such as 'return'
Use trailing underscores in parameter names, type names, struct fields, class members, etc. to avoid name clashes with keywords. The trailing underscores in identifier names are invisible in the SOAP/XML payload. For example "mymethod(int &return_);" declares a remote method with output parameter "return_" which will be (de)serialized in XML as "return".
How do I write a remote method that has no input parameters?
Just specify one output parameter. Some C/C++ compilers will not compile the gSOAP-generated codes due to an empty struct created by gSOAP. To circumvent this problem, use void* as a dummy input parameter, e.g. "ns__myMethod(void*_, int &return_);". The void* parameter will not be (de)serialized.
I have a remote method with a response struct that is also used as a type elsewhere in my header file, but now my WSDL is incomplete because the type is not defined in the WSDL (an element definition appears instead).
A response struct/class is not a type but a placeholder or wrapper for the result parameters. So you cannot use this struct/class anywhere else in your type definitions, since it will be defined as a schema element rather than a schema type. For example:
struct ns__data { ... };
int ns__example(..., struct ns__data *out);
where the ns__data struct contains the result parameters of the method. The struct is translated into an element definition in the generated WSDL to support doc/lit style messaging. As you can see, this means that ns__data cannot be used as a type anywhere else in your header file. To work around this problem, use:
struct ns__data { ... };
int ns__example(..., struct ns__exampleResponse { struct ns__data out; } *out);
Now we have a type ns__data and a response struct for the method results.
How do I write a remote method that has no output parameters?
Specify an empty struct output parameter. For example: "ns__myMethod(..., struct ns__myMethodResponse { } &response)". Some C/C++ compilers will not compile the empty struct. To circumvent this problem, use void* as a dummy field, e.g. "ns__myMethod(..., struct ns__myMethodResponse { void*_; } &response)" The void* field will not be (de)serialized.
How can I use (wide character) strings for doc/literal encoding to (de)serialize any form of XML?
Declare:
typedef char *XML;
or
typedef wchar_t *XML;
and use either XML type for mixed-content strings (strings that contain XML).
How do I add SOAP Headers to my messages?
In gSOAP 1.X set the global "soap_header" variable to point to a SOAP_ENV__Header data structure. The declaration of the fields in this data structure can be specified in the header file input to the compiler for customized header processing.
In gSOAP 2.X set the "header" field of the runtime environment variable (e.g. "soap") to point to a "struct SOAP_ENV__Header" (e.g. "soap.header = malloc(sizeof(struct SOAP_ENV__Header))". The declaration of the fields in this data structure can be specified in the header file input to the compiler.
What is Genivia inc?
gSOAP is copyrighted and owned by Robert A. van Engelen. Genivia inc. is a small company founded by Robert A. van Engelen to distribute gSOAP with a public open source license, to provide software support, and for consulting purposes.