【问题标题】:Segmentation fault and undefined reference to `dlopen'分段错误和对“dlopen”的未定义引用
【发布时间】:2016-03-16 11:23:33
【问题描述】:

我尝试在 C++ 中动态加载库。我遵循this 教程。 我的文件夹结构是这样的:

├── main.cpp
├── testLib.cpp
├── testLib.h
├── testLib.so
└── testVir.h

ma​​in.cpp

#include<iostream>
#include<dlfcn.h>
#include<stdio.h>
#include "testVir.h"

using namespace std;

int main()
{
    void *handle;
    handle = dlopen("./testLib.so", RTLD_NOW);
    if (!handle)
    {
           printf("The error is %s", dlerror());
    }

    typedef TestVir* create_t();
    typedef void destroy_t(TestVir*);

    create_t* creat=(create_t*)dlsym(handle,"create");
    destroy_t* destroy=(destroy_t*)dlsym(handle,"destroy");
    if (!creat)
    {
           cout<<"The error is %s"<<dlerror();
    }
    if (!destroy)
    {
           cout<<"The error is %s"<<dlerror();
    }
    TestVir* tst = creat();
    tst->init();
    destroy(tst);
    return 0 ;
}

testLib.cpp

#include <iostream>
#include "testVir.h"
#include "testLib.h"

using namespace std;
void TestLib::init()
{
   cout<<"TestLib::init: Hello World!! "<<endl ;
}

//Define functions with C symbols (create/destroy TestLib instance).
extern "C" TestLib* create()
{
    return new TestLib;
}
extern "C" void destroy(TestLib* Tl)
{
   delete Tl ;
}

testLib.h

#ifndef TESTLIB_H
#define TESTLIB_H

class TestLib
{
 public:
     void init();
};

#endif

testVir.h

#ifndef TESTVIR_H
#define TESTVIR_H

class TestVir
{
public:
  virtual void init()=0;
};

#endif

我使用这个命令得到了我的testLib.so g++ -shared -fPIC testLib.cpp -o testLib.so , 这很好用,但是当我尝试用 g++ -ldl main.cpp -o test 我得到这个错误:

/tmp/ccFoBr2X.o: In function `main':
main.cpp:(.text+0x14): undefined reference to `dlopen'
main.cpp:(.text+0x24): undefined reference to `dlerror'
main.cpp:(.text+0x47): undefined reference to `dlsym'
main.cpp:(.text+0x5c): undefined reference to `dlsym'
main.cpp:(.text+0x6c): undefined reference to `dlerror'
main.cpp:(.text+0x95): undefined reference to `dlerror'
collect2: error: ld returned 1 exit status

G++ 版本(来自g++ --version):
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4

我不知道发生了什么,我需要一些资源来了解它是如何工作的。

编辑 1 我通过使用这个命令来编译我的 main.js 解决了这个问题。 g++ main.cpp -ldl -o test。在 answer 中找到此修复程序。

但现在当我尝试运行./test 时,我得到Segmentation fault。而且看起来 在这一行 tst-&gt;init(); 但指针看起来有效。

编辑 2 按照this 教程我得到同样的错误,Segmentation fault

如果你有好的教程或文档,那真的很有帮助。

【问题讨论】:

  • 这行得通:static_cast(tst)->init()
  • 您需要将链接器标志移动到命令的末尾:g++ main.cpp -o test -ldl
  • 另外,根据手册,您应该在从dlsym() 分配时将符号指针转换为 (void**),因为直接转换可能会在某些系统上丢失位。请参阅手册中的示例:linux.die.net/man/3/dlopen 他们这样做*(void**) (&amp;create) = dlsym(handle, "create");

标签: c++ gcc g++ shared-libraries


【解决方案1】:

这与dlopen 部分无关。您的 class TestLib 缺少来自 TestVir 的继承:

class TestLib : public TestVir

您还应该将create/destroy 签名修复为相同类型。既然要隐藏TestLib类,就应该返回并取TestVir*

extern "C" TestVir* create()
{
    return new TestLib();
}
extern "C" void destroy(TestVir* Tl)
{
   delete Tl ;
}

还要将函数类型放入标题中,否则一段时间后您将自取其辱。为此,您还必须have virtual destructor in the base class.

class TestVir
{
public:
    virtual void init()=0;
    virtual ~TestVir() = default; // note: C++11
};

顺便说一句:您的错误处理缺少刷新,如果出现错误,您不应该继续。

【讨论】:

  • 您有任何我可以阅读的文档或有关此主题的教程吗?谢谢您的帮助。
  • @Matei 我想《Effective C++》一书,第 7 项将是一个很好的起点。根据您的 C++ 知识,诸如“The C++ Programming Language, 4th Edition”之类的基础书籍可能对您有所帮助。与动态库加载和 C++ 的组合既不是很常见,也不是特别优雅(不幸的是),但如果您更精通语言本身和writing librariesdlopen 部分并不那么复杂。
  • @Matei 还有Boost.DLL,但我没有这方面的个人经验。
猜你喜欢
  • 2010-10-31
  • 2015-02-20
  • 1970-01-01
  • 2012-05-25
  • 2016-08-07
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 2012-10-10
相关资源
最近更新 更多