在Android平台上使用dlclose(…)时的分段错误

在Android平台上使用dlclose(…)时的分段错误,第1张

概述在 Android上使用动态加载API(< dlfcn.h&gt ;:dlopen(),dlclose()等)时,我有一些问题. 我使用NDK独立工具链(版本8)来编译应用程序和库. Android版本是2.2.1 Froyo. 以下是简单共享库的源代码. #include <stdio.h>int iii = 0;int *ptr = NULL;__attribute__((const 在 Android上使用动态加载API(< dlfcn.h&gt ;:dlopen(),dlclose()等)时,我有一些问题.
我使用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(…)时的分段错误所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1132000.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-30
下一篇2022-05-30

发表评论

登录后才能评论

评论列表(0条)

    保存