linux c解决多个第三方so动态库包含不同版本openssl造成的符号冲突【转载】
linux c解决多个第三方so动态库包含不同版本openssl造成的符号冲突
此次只记录了解决方法,详细原因和分析见原文。
解决办法
Dynamic loading of shared library with RTLD_DEEPBIND
当我一dlopen中加了参数RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND之后,程序功能正常了,正常了!
这个困扰我几天的问题,就这样戏剧性地解决掉了。
When we are supposed to use RTLD_DEEPBIND? 说明了原因:
You should use RTLD_DEEPBIND when you want to ensure that symbols looked up in the loaded library start within the library, and its dependencies before looking up the symbol in the global namespace.
This allows you to have the same named symbol being used in the library as might be available in the global namespace because of another library carrying the same definition; which may be wrong, or cause problems.
当希望dlopen载入的库首先从自己和它的依赖库中查找符号,然后再去全局符号中去查找时,就用RTLD_DEEPBIND。这样就允许dlopen载入的库中存在与全局符号重名的符号,而对这个载入的库来说错的或者可能引起问题的全局符号可能是由其它库引入的。
现在,libcurl用dlopen方式运行时动态加载,加载时使用RTLD_DEEPBIND参数,这样,它就会首先从libcurl.so以及它所依赖的其它库中查找符号,从而避免了使用有问题的全局符号。
相关的程序片段
//用cURLpp发送RESTful post 请求
int DingDing::post_request_curl(const std::string& url, const std::string& jsonBody, std::string& strReturn)
{
void *handle;
static CURLcode (*f_global_init)(long) = NULL;
static CURL *(*f_easy_init)(void) = NULL;
static struct curl_slist *(*f_slist_append)(struct curl_slist *, const char *) = NULL;
static CURLcode (*f_easy_setopt)(CURL *, CURLoption, ...) = NULL;
static CURLcode (*f_easy_perform)(CURL *) = NULL;
static void (*f_easy_cleanup)(CURL *) = NULL;
static void (*f_global_cleanup)(void) = NULL;
char *error;
//handle = dlopen ("libcurl.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
handle = dlopen ("libcurl.so", RTLD_LAZY | RTLD_DEEPBIND);
//handle = dlopen ("libcurl.so", RTLD_LAZY | RTLD_LOCAL);
if (!handle) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
dlerror(); /* Clear any existing error */
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_global_init = (CURLcode (*)(long)) dlsym(handle, "curl_global_init");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_easy_init = (CURL *(*)(void)) dlsym(handle, "curl_easy_init");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_slist_append = (struct curl_slist *(*)(struct curl_slist *, const char *))
dlsym(handle, "curl_slist_append");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_easy_setopt = (CURLcode (*)(CURL *, CURLoption, ...)) dlsym(handle, "curl_easy_setopt");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_easy_perform = (CURLcode (*)(CURL *)) dlsym(handle, "curl_easy_perform");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_easy_cleanup = (void (*)(CURL *)) dlsym(handle, "curl_easy_cleanup");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
f_global_cleanup = (void (*)(void)) dlsym(handle, "curl_global_cleanup");
if ((error = dlerror()) != NULL) {
LOGINFO << "载入libcurl库出错,错误信息:" << dlerror();
exit(1);
}
CURL *ch;
CURLcode rv;
f_global_init(CURL_GLOBAL_ALL);
ch = f_easy_init();
struct curl_slist *chunk = NULL;
chunk = f_slist_append(chunk, "Content-Type: application/json");
f_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
f_easy_setopt(ch, CURLOPT_HTTPHEADER, chunk);
//curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
f_easy_setopt(ch, CURLOPT_POSTFIELDS, jsonBody.c_str());
//curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
//curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
//curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, *writefunction);
//curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
//curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, *writefunction);
//curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
//curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
f_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0L);
f_easy_setopt(ch, CURLOPT_URL, url.c_str());
/* Turn off the default CA locations, otherwise libcurl will load CA
* certificates from the locations that were detected/specified at
* build-time
*/
//curl_easy_setopt(ch, CURLOPT_CAINFO, NULL);
//curl_easy_setopt(ch, CURLOPT_CAPATH, NULL);
/* first try: retrieve page without ca certificates -> should fail
* unless libcurl was built --with-ca-fallback enabled at build-time
*/
rv = f_easy_perform(ch);
if(rv == CURLE_OK)
LOGINFO << "libcurl请求发送成功";
else
LOGINFO << "libcurl请求发送失败";
f_easy_cleanup(ch);
f_global_cleanup();
return rv;
}

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)