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;
}



原文链接https://blog.youkuaiyun.com/found/article/details/105263450

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值