user-0 提问: linux c++ 动态链接库运行报错

回复:
user: user-1
content: 请问楼主这个问题解决了吗，我也遇到了样的问题。

user: user-0
content: 我手动写了一个test程序，没有任何业务逻辑 g++ -g test.c   ./a.out ./libPGWDecode.so a.txt . 就能正常调用libPGWDecode.so这个动态链接库  用我们的应用程序就报上面的错误。  但是我们应用程序调用其他动态库也能成功，就这个动态库有问题。测试程序代码如下  #include <dlfcn.h> #include <string.h> #include <stdio.h>  //初始化库环境 typedef int (*Func_InitEnv)(char* pMsg);  //执行转换函数 typedef int (*Func_CallFunc)(char* pSrcName,char* pSrcPath,char* pOutName,int* iRecordCount,char* pMsg);  //释放库环境 typedef int (*Func_UnInitEnv)(char* pMsg);  void* pLibHandle; //动态库句柄  Func_InitEnv pInit; //初始化函数句柄  Func_CallFunc pCallFunc; //执行函数句柄  Func_UnInitEnv pUnInit; //释放函数句柄  int InitFtpLib(char* pLibName,char* pMsg) { 	pLibHandle = dlopen(pLibName,RTLD_LAZY); 	if(pLibHandle == NULL) 	{ 		sprintf(pMsg,"打开库[%s]失败.ERR:%s",pLibName,dlerror()); 	  	return -1; 	}  	pInit = (Func_InitEnv)dlsym(pLibHandle,"InitEnv"); 	if(pInit == NULL) 	{ 		sprintf(pMsg,"打开库[%s]函数[InitEnv]失败.ERR:%s",pLibName,dlerror()); 		return -1; 	}  	pUnInit = (Func_InitEnv)dlsym(pLibHandle,"UnInitEnv"); 	if(pUnInit == NULL) 	{ 		sprintf(pMsg,"打开库[%s]函数[UnInitEnv]失败.ERR:%s",pLibName,dlerror()); 		return -1; 	}  	pCallFunc = (Func_CallFunc)dlsym(pLibHandle,"CallFunc"); 	if(pCallFunc == NULL) 	{ 		sprintf(pMsg,"打开库[%s]函数[CallFunc]失败.ERR:%s",pLibName,dlerror()); 		return -1; 	}  	//执行初始化  	return pInit(pMsg); }  int CallLibFunc(char* pSrcName,char* pSrcPath,char* pOutName,int* iRecordCount,char* pMsg) { 	return pCallFunc(pSrcName,pSrcPath,pOutName,iRecordCount,pMsg); }  int UnInitFtpLib(char* pMsg) { 	return pUnInit(pMsg); }  //char* libname,char* pSrcName,char* pSrcPath //a.out libgetrecordnum.so GetRecordNum.cpp ./  int main(int argc,char **argv) { 	char msg[256]; 	char outname[256]; 	int count = 0;  	if(argc < 3)         {               printf("输入参数有误：需要3个参数\n"); 		return 0;         }  	count = 0; 	if(-1 == InitFtpLib(argv[1],msg)) 	{ 	    printf("%s\n",msg); 	    return 0; 	}  	CallLibFunc(argv[2],argv[3],outname,&count,msg);  	UnInitFtpLib(msg);  	printf("outname=%s,recordcount=%d,msg=%s\n",outname,count,msg);  	return 0; }

user: user-2
content: 使用gdb单步调试进入函数，检查调用约定（参数传递方式，参数个数，堆栈是否平衡，参数类型，参数取值范围，……）  调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx

user: user-3
content: 看起来像传参的问题，关键应该是看调用部分吧

user: user-0
content: pLibHandle = dlopen(pLibName,RTLD_LAZY); 	if(pLibHandle == NULL) 	{ 		sprintf(pMsg,"打开库[%s]失败.ERR:%s",pLibName,dlerror()); 	  	return -1; 	}   	pCallFunc = (Func_CallFunc)dlsym(pLibHandle,"CallFunc"); 	if(pCallFunc == NULL) 	{ 		sprintf(pMsg,"打开库[%s]函数[CallFunc]失败.ERR:%s",pLibName,dlerror()); 		return -1; 	}  int ftplib::CallLibFunc(char* pSrcName,char* pSrcPath,char* pOutName,int* iRecordCount,char* pMsg) { 	return pCallFunc(pSrcName,pSrcPath,pOutName,iRecordCount,pMsg); }  gdb 报错信息  ftplib::CallLibFunc (pSrcName=0x7fffffff8b60 "bss96.ecld.com_DATA_TEST30_BB000000003300.dat",      pSrcPath=0x7fffffff9f80 "/home/bill/data/collect/data/collect_tmp0/12155", pOutName=0x685884 "", iRecordCount=0x7fffffffa698,      pMsg=0x7fffffff9980 "") at /home/bill/src_smz/collect_multiprocess/ftplib.cpp:48 	return pCallFunc(pSrcName,pSrcPath,pOutName,iRecordCount,pMsg);  Program received signal SIGSEGV, Segmentation fault. 0x00007fffef9393ea in CallFunc (pSrcName=<error reading variable: Cannot access memory at address 0x7fffffcf4108>,      pSrcPath=<error reading variable: Cannot access memory at address 0x7fffffcf4100>,      pOutName=<error reading variable: Cannot access memory at address 0x7fffffcf40f8>,      iRecordCount=<error reading variable: Cannot access memory at address 0x7fffffcf40f0>,      pMsg=<error reading variable: Cannot access memory at address 0x7fffffcf40e8>) at PGWDecode.cpp:54 54	{

user: user-2
content: 引用 5 楼 qq_33404788 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 使用gdb单步调试进入函数，检查调用约定（参数传递方式，参数个数，堆栈是否平衡，参数类型，参数取值范围，……）  调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx 你好，怎么查看？[/quote] 汇编功底不深还真看不懂。 你干脆用“创建子进程，命令行传参进你的test程序，修改你的test程序将结果数据保存到临时文本文件或发送到标准输出，读取结果文件或读取重定向后标准输出，得到调用结果”的办法隔离直接调用出错问题。

user: user-0
content: 引用 3 楼 zhao4zhong1 的回复:使用gdb单步调试进入函数，检查调用约定（参数传递方式，参数个数，堆栈是否平衡，参数类型，参数取值范围，……）  调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx 你好，怎么查看？