我正在研究通过调用脚本自动加载所有*.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;
}
答案 0 :(得分:3)
我会使用像gdb
这样的调试器。
如果您无法使用它,请尝试在执行strace
ltrace
或dlopen
另外,在调用errno
之前清除dlopen
并在失败的dlopen
之后显示它(或在调试器下打印)。
使用file
,objdump
和nm -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
宏(如果确实 宏)是什么扩展到了,dlopen
,dlmopen
,dlsym
和dlvsym
上设置断点,然后观察其中一个被称为之后> 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
。