简体   繁体   English

从共享库的导出 function 获取实例时 dlopen 分段错误错误

[英]dlopen Segmentation fault error when get a instance from shared library's exported function

I have been stuck in a problem for several days when using dlopen/dlsym to deal with the shared object.在使用dlopen/dlsym处理共享的 object 时,我已经陷入了几天的问题。 I desperately need your help!我迫切需要你的帮助!

There are three headers/source files: Animal.h, Animal.cpp and test.cpp , and two products: libanimal.so and a.out .共有三个头文件/源文件: Animal.h、Animal.cpptest.cpp ,以及两个产品: libanimal.soa.out

Here is the source code:这是源代码:

Animal.h:动物.h:

// Animal.h
#ifndef STDLIB_ANIMAL_H
#define STDLIB_ANIMAL_H
#include <string>

class Animal {
public:
    Animal();
    std::string shout();
};

extern "C" Animal* createAnimal();

#endif //STDLIB_ANIMAL_H

Animal.cpp动物.cpp

// Animal.cpp
#include "Animal.h"

Animal::Animal() = default;

std::string Animal::shout() {
    return "WOW";
}

Animal* createAnimal() {
    return new Animal();
}

and the last one test.cpp which contained the main entry of the application:最后一个test.cpp包含应用程序的主要条目:

// test.cpp
#include <cstdio>
#include <cstdlib>
#include <string>
#include <dlfcn.h>
#include <iostream>
#include "Animal.h"

int main(int argc, char** argv)
{
    void *handle;
    // Open shared library
    handle = dlopen("./libanimal.so", RTLD_LAZY);
    if (!handle) {
        /* fail to load the library */
        fprintf(stderr, "Handle Error: %s\n", dlerror());
        return EXIT_FAILURE;
    }

    auto spawnAnimal = reinterpret_cast<Animal* (*)()>(dlsym(handle, "createAnimal"));

    if (!spawnAnimal) {
        /* no such symbol */
        fprintf(stderr, "No Such Symbol Error: %s\n", dlerror());
        dlclose(handle);
        return EXIT_FAILURE;
    }
    auto animal = spawnAnimal();
    std::cout << "call animal shout, the address of animal : " << animal <<std::endl;
    std::cout << animal->shout() << std::endl;
    std::cout << "after calling" << std::endl;
    dlclose(handle);

    return EXIT_SUCCESS;
}

First, I built libanimal.so shared library by the following command:首先,我通过以下命令构建了 libanimal.so共享库:

$ g++ -shared -fPIC -Wall -o libanimal.so Animal.cpp -std=c++0x

Then I built the executable, a.out :然后我构建了可执行文件a.out

$ g++ -Wall test.cpp -ldl -std=c++0x -Wl,--unresolved-symbols=ignore-in-object-files
# --unresolved-symbols=ignore-all: tell linker to stop complaining about missing symbols

Both the above commands ran well without any error, but when I execute a.out , errors came out:上述两个命令都运行良好,没有任何错误,但是当我执行a.out时,出现了错误:

$ ./a.out
call animal shout, the address of animal : 0x7fffe97a4520
Segmentation fault (core dumped)

I have searched lots of blogs/documentations, but all of them just post a really simple example:我搜索了很多博客/文档,但所有这些都只是发布了一个非常简单的示例:
The function they export always return like a std::string or char or int which is built-in type, not something like a object of a user-defined class, just like the showcase above (the createAnimal function).他们导出的 function 总是像 std::string 或 char 或 int 那样返回,它是内置类型,而不是像用户定义的class函数的 object 一样返回。

So what's wrong with this?那么这有什么问题呢? Could you please help me figuring out?你能帮我弄清楚吗?
Thank you !谢谢 !

BTW, my environment is:顺便说一句,我的环境是:

$ g++ --version
g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Ok, my suspicion from the comment has confirmed itself.好的,我对评论的怀疑已经得到证实。 The problem is with the early binding on animal->shout() which resolves at compile time to a call to _ZN6Animal5shoutB5cxx11Ev and this symbol is nowhere to be found.问题在于animal- animal->shout()的早期绑定,它在编译时解析为对_ZN6Animal5shoutB5cxx11Ev的调用,并且找不到该符号。

If I change it to virtual (late binding, resolved at runtime through a vtable):如果我将其更改为虚拟(后期绑定,在运行时通过 vtable 解决):

// Animal.h
#ifndef STDLIB_ANIMAL_H
#define STDLIB_ANIMAL_H
#include <string>

class Animal {
public:
    Animal();
    virtual std::string shout();
    virtual ~Animal() {} // always put a virtual destructor if you have any virtual methods
};

extern "C" Animal* createAnimal();

#endif //STDLIB_ANIMAL_H

Now it runs.现在它运行了。

You have an unresolved symbol in your main executable.您的主可执行文件中有一个未解析的符号 Do not ignore these error messages.不要忽略这些错误消息。

./tmp/cchZxfAz.o: In function `main':
test.cpp:(.text+0x112): undefined reference to `Animal::shout[abi:cxx11]()'
collect2: error: ld returned 1 exit status

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM