如果dlopen()失败,dlerror()如何返回NULL?

时间:2011-12-17 19:31:59

标签: c linux ubuntu shared-libraries

我正在研究通过调用脚本自动加载所有*.so模块库的系统。

我尝试更新其中一个模块以支持XML-RPC。我在Ubuntu 10.10上使用了库ibxmlrpc-c3-dev。我的更改后dlopen()失败并且dlerror()返回NULL的问题。编译不会返回任何错误。

如何调试和修复此问题?以下是代码:

#include "stdlib.h"
#include "stdio.h"
#ifndef WIN32
#include "unistd.h"
#endif

#include "xmlrpc-c/base.h"
#include "xmlrpc-c/server.h"
#include "xmlrpc-c/server_abyss.h"

#include "config.h"  /* information about this build environment */

而且,我添加了这个函数,即使dlopen()失败,大多数行都被注释掉了:

int RPC_Server(int           const port) {

   // xmlrpc_server_abyss_parms serverparm;
    //xmlrpc_registry * registryP;
    xmlrpc_env env;



    xmlrpc_env_init(&env);

    //registryP = xmlrpc_registry_new(&env);

   // xmlrpc_registry_add_method(
    //    &env, registryP, NULL, "sample.add", &sample_add, NULL);

    /* In the modern form of the Abyss API, we supply parameters in memory
       like a normal API.  We select the modern form by setting
       config_file_name to NULL:
    */
  //  serverparm.config_file_name = NULint
    RPC_Server(int           const port) {

       // xmlrpc_server_abyss_parms serverparm;
        //xmlrpc_registry * registryP;
        xmlrpc_env env;



        xmlrpc_env_init(&env);

        //registryP = xmlrpc_registry_new(&env);

       // xmlrpc_registry_add_method(
        //    &env, registryP, NULL, "sample.add", &sample_add, NULL);

        /* In the modern form of the Abyss API, we supply parameters in memory
           like a normal API.  We select the modern form by setting
           config_file_name to NULL:
        */
      //  serverparm.config_file_name = NULL;
       // serverparm.registryP        = registryP;
       // serverparm.port_number      = port;
       // serverparm.log_file_name    = "/tmp/xmlrpc_log";

       // printf("Running XML-RPC server...\n");

       // xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));

        /* xmlrpc_server_abyss() never returns */

        return 0;
    }L;
   // serverparm.registryP        = registryP;
   // serverparm.port_number      = port;
   // serverparm.log_file_name    = "/tmp/xmlrpc_log";

   // printf("Running XML-RPC server...\n");

   // xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));

    /* xmlrpc_server_abyss() never returns */

    return 0;
}

这是用于加载模块的代码

#ifndef RTLD_NOW

#define RTLD_NOW DL_LAZY
#endif   
void* handle;
char* error;


handle=dlopen(mod->binary_file, RTLD_NOW); 

if (!handle){
LOG( " could not open file [%s]: %s\n",
    mod_cfg->binary_file, dlerror() );
return 0;
}

4 个答案:

答案 0 :(得分:3)

我会使用像gdb这样的调试器。

如果您无法使用它,请尝试在执行strace

的流程中使用ltracedlopen

另外,在调用errno之前清除dlopen并在失败的dlopen之后显示它(或在调试器下打印)。

使用fileobjdumpnm -D检查您的dlopen - ed *.so文件是否具有所有必需的属性(例如符号)。

执行dlopen的进程的内存地址空间可能已满(或已达到某些资源限制),malloc内的某些内部libdl.so失败(例如, dlerror)。

答案 1 :(得分:1)

在此代码中:

handle=dlopen(mod->binary_file, RTLD_NOW); 

if (!handle) {
    LOG( " could not open file [%s]: %s\n",
         mod_cfg->binary_file, dlerror() );

我可以想到dlerror()返回NULL的最有可能的方法是LOG本身是否调用dl*例程之一(这会清除错误)说明dlerror返回)。

所以,

  • 向我们展示LOG宏(如果确实 宏)是什么扩展到了,
  • 在GDB下运行程序,在dlopendlmopendlsymdlvsym上设置断点,然后观察其中一个被称为之后 em>您在致电dlopen之前致电dlerror

答案 2 :(得分:0)

handle=dlopen(mod->binary_file, RTLD_NOW); 

if (!handle){
string errmsg = string(dlerror());
LOG( " could not open file [%s]: %s\n",
    mod_cfg->binary_file, errmsg.c_str() );
return 0;
}

使用BoostLog时遇到相同的问题,以上是我的解决方案。 我想LOG会影响dlerror()。

答案 3 :(得分:-1)

最重要的是,你绝对应该使用dlerror