怎么完美调用gSoap库呢?
首先与用的是stdsoap2.c还是stdsoap2.cpp有关。
我这里举例内编的是stdsoap2.cpp,那么一个WebService调用过程如下:
1
2
3
4
5
6
7
8
9
10
11
12
| void aWebServiceCall()
{
struct soap soapCtx;
soap_call___ns1__XXX(&soapCtx, url.c_str(), ...);
if (soapCtx.error)
{
printf("soap error: %d, %s, %s\n", soapCtx.error, *soap_faultcode(&soapCtx), *soap_faultstring(&soapCtx));
}
soap_end(&soapCtx);
} |
void aWebServiceCall()
{
struct soap soapCtx;
soap_call___ns1__XXX(&soapCtx, url.c_str(), ...);
if (soapCtx.error)
{
printf("soap error: %d, %s, %s\n", soapCtx.error, *soap_faultcode(&soapCtx), *soap_faultstring(&soapCtx));
}
soap_end(&soapCtx);
}
看到没,C++版的soap只需要在每次调完soap_call___ns1__XXX之类的接口后,调用一次soap_end就完事了,这是完美的写代码流程。但实际运行后还是有内存泄露,研究发现,这个内存泄露是由于OpenSSL的屁股没揩干净造成的。最终无leak的结尾函数如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| void doSSLLeftCleanup()
{
// thread-local cleanup
ERR_remove_state(0);
// thread-safe cleanup
CONF_modules_unload(1);
// global application exit cleanup (after all SSL activity is shutdown)
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
int i, n;
STACK_OF(SSL_COMP) *ssl_comp_methods;
ssl_comp_methods = SSL_COMP_get_compression_methods();
n = sk_SSL_COMP_num(ssl_comp_methods);
for (i = 0; i < n; i++)
{
(void)sk_SSL_COMP_delete(ssl_comp_methods, i);
}
sk_SSL_COMP_free(ssl_comp_methods);
} |
void doSSLLeftCleanup()
{
// thread-local cleanup
ERR_remove_state(0);
// thread-safe cleanup
CONF_modules_unload(1);
// global application exit cleanup (after all SSL activity is shutdown)
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
int i, n;
STACK_OF(SSL_COMP) *ssl_comp_methods;
ssl_comp_methods = SSL_COMP_get_compression_methods();
n = sk_SSL_COMP_num(ssl_comp_methods);
for (i = 0; i < n; i++)
{
(void)sk_SSL_COMP_delete(ssl_comp_methods, i);
}
sk_SSL_COMP_free(ssl_comp_methods);
}
但遗憾的是,对于openssl-1.0.1p,SSL_COMP_get_compression_methods返回的是一个内部静态变量,没有导出函数可以将其置为NULL,也即doSSLLeftCleanup不能调第二次,所以,请在所有的最后的最后调一次。但这也从另一方面说明,这种内存泄露是不会累加的,不管gSoap接口函数调用多少次。
注:这里的gSoap版本为:2.8.37