
我使用NDK独立工具链(版本8)来编译应用程序和库.
AndroID版本是2.2.1 Froyo.
以下是简单共享库的源代码.
#include <stdio.h>int iii = 0;int *ptr = NulL;__attribute__((constructor))static voID init(){ iii = 653;}__attribute__((destructor))static voID cleanup(){}int aaa(int i){ printf("aaa %d\n",iii);} 这是使用上述库的程序源代码.
#include <dlfcn.h>#include <stdlib.h>#include <stdio.h>int main(){ voID *handle; typedef int (*func)(int); func bbb; printf("start...\n"); handle = dlopen("/data/testt/test.so",RTLD_LAZY); if (!handle) { return 0; } bbb = (func)dlsym(handle,"aaa"); if (bbb == NulL) { return 0; } bbb(1); dlclose(handle); printf("exit...\n"); return 0;} 有了这些资源,一切都运行正常,但是当我尝试使用一些STL函数或类时,当main()函数退出时,程序会崩溃,例如当使用该源代码进行共享库时.
#include <iostream>using namespace std;int iii = 0;int *ptr = NulL;__attribute__((constructor))static voID init(){ iii = 653;}__attribute__((destructor))static voID cleanup(){}int aaa(int i){ cout << iii << endl;} 使用此代码,程序会在分段故障后或在main()函数退出时崩溃.
我已经尝试过几次测试,并发现以下结果.
>没有使用STL,一切都正常.
>当使用STL并且最后不要调用dlclose()时,一切都正常.
>我尝试使用-fno-use-cxa-atexit或-fuse-cxa-atexit等各种编译标记进行编译,结果是一样的.
在使用STL的代码中有什么问题?
解决方法 看起来我发现了这个BUG的原因.我已经尝试过另一个例子,其中包含以下源文件:这是简单类的源代码:
myclass.h
class MyClass{public: MyClass(); ~MyClass(); voID Set(); voID Show();private: int *pArray;}; myclass.cpp
#include <stdio.h>#include <stdlib.h>#include "myclass.h"MyClass::MyClass(){ pArray = (int *)malloc(sizeof(int) * 5);}MyClass::~MyClass(){ free(pArray); pArray = NulL;}voID MyClass::Set(){ if (pArray != NulL) { pArray[0] = 0; pArray[1] = 1; pArray[2] = 2; pArray[3] = 3; pArray[4] = 4; }}voID MyClass::Show(){ if (pArray != NulL) { for (int i = 0; i < 5; i++) { printf("pArray[%d] = %d\n",i,pArray[i]); } }} 从代码中可以看出,我没有使用任何与STL相关的东西.
这是函数库导出的源文件.
func.h
#ifdef __cplusplusextern "C" {#endifint SetBabe(int);int ShowBabe(int);#ifdef __cplusplus}#endif func.cpp
#include <stdio.h>#include "myclass.h"#include "func.h"MyClass cls;__attribute__((constructor))static voID init(){}__attribute__((destructor))static voID cleanup(){}int SetBabe(int i){ cls.Set(); return i;}int ShowBabe(int i){ cls.Show(); return i;} 最后这是使用库的程序的源代码.
main.cpp中
#include <dlfcn.h>#include <stdlib.h>#include <stdio.h>#include "../simple_lib/func.h"int main(){ voID *handle; typedef int (*func)(int); func bbb; printf("start...\n"); handle = dlopen("/data/testt/test.so",RTLD_LAZY); if (!handle) { printf("%s\n",dlerror()); return 0; } bbb = (func)dlsym(handle,"SetBabe"); if (bbb == NulL) { printf("%s\n",dlerror()); return 0; } bbb(1); bbb = (func)dlsym(handle,"ShowBabe"); if (bbb == NulL) { printf("%s\n",dlerror()); return 0; } bbb(1); dlclose(handle); printf("exit...\n"); return 0;} 再次,你可以看到程序使用库也没有使用任何STL相关的东西,但在程序运行后,我得到相同的分段错误在主(…)功能退出.所以这个问题与STL本身没有联系,它隐藏在别的地方.经过长时间的研究,我发现了这个BUG.通常,静态C变量的析构函数会在main(…)函数退出之前立即被调用,如果它们在main程序中定义,或者如果它们在某个库中定义并且正在使用它,那么析构函数应该立即被调用dlclose(…).在AndroID *** 作系统上,在main(…)函数退出时调用静态C变量的所有析构函数(在主程序中定义或在某些库中使用).那么在我们的情况下会发生什么呢?我们在我们使用的库中定义了cls static C变量.然后在main(…)函数退出之前,我们调用dlclose(…)函数,结果库关闭,cls变为无效.但是cls的指针存储在某个地方,在main(…)函数退出时应该调用析构函数,因为在调用时它已经无效了,我们得到了分段错误.所以解决方案是不要调用dlclose(…),一切都应该是好的.不幸的是,使用这个解决方案,我们不能使用attribute((destructor))来对要重新初始化的东西进行初始化,因为它被调用为dlclose(…)调用的结果.
总结以上是内存溢出为你收集整理的在Android平台上使用dlclose(…)时的分段错误全部内容,希望文章能够帮你解决在Android平台上使用dlclose(…)时的分段错误所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)