Linux c++.在预加载的共享库中定义的基类的崩溃调用函数
Linux c++. Crash calling function of base class defined inside preloaded shared library
我正在尝试创建一个包含基类的共享库,以便可以派生它:
碱基.h
class Base
{
public:
virtual ~Base () {}
virtual void Function ();
};
基地.cpp
#include <stdio.h>
#include "base.h"
void Base::Function ()
{
printf ("base functionn");
}
mybase.so
g++ -fpic -g -shared base.cpp -o libbase.so
主.cpp
#include "base.h"
class Derived : public Base
{
};
int main (int argc, char** argv)
{
Derived* d = new Derived ();
d->Function ();
delete d;
return 1;
}
我还想避免将可执行文件与共享库链接,因此我通过忽略未解析的符号来创建它:
测试
g++ -fpic -rdynamic -Wl,--unresolved-symbols=ignore-in-object-files -g main.cpp -o test
最后LD_PRELOAD我使用环境变量在执行前预加载共享库
LD_PRELOAD=./libbase.so ./test
Segmentation fault (core dumped)
我注意到问题是派生对象的虚拟表未为"函数"定义:
(gdb) info vtbl d
vtable for 'Derived' @ 0x601030 (subobject @ 0x602010):
[0]: 0x400c7e <Derived::~Derived()>
[1]: 0x400cc0 <Derived::~Derived()>
[2]: 0x0
我的猜测是,当可执行文件加载时,动态链接器无法解析 vtable 条目,因为共享库尚未加载。
所以我的问题是:有没有办法做到这一点?也许强制以某种方式在可执行文件之前加载共享库......
顺便说一句:通过使"函数"非虚拟,一切都可以正常工作,因为派生类不需要 vtable。
更新 1:使用对象代替指针使 main 工作:
int main (int argc, char** argv)
{
Derived d;
d.Function (); // prints "base function"
return 1;
}
更新 2:在主库中执行与在第二个共享库中相同的操作也可以:
米利布.cpp
#include "base.h"
class DerivedLib : public Base
{
};
extern "C" void do_function()
{
DerivedLib* d = new DerivedLib();
d->Function();
delete d;
}
mylib.so
g++ -fPIC -g -shared lib.cpp -o libmylib.so
主.cpp
#include "base.h"
#include <dlfcn.h>
class Derived : public Base
{
};
int main (int argc, char** argv)
{
void* handle = dlopen("libmylib.so", RTLD_LAZY);
void (*do_function)();
do_function = (void (*)())dlsym(handle, "do_function");
do_function(); // prints "base function"
Derived* d = new Derived();
d->Function (); // <- crashes
delete d;
return 1;
}
因此,在可执行文件中创建新的实例指针时,肯定会出现问题
如果您尝试不链接到共享库的原因是您希望在不破坏可执行文件的情况下继续更改共享库,那么实际上,只要您不更改正在使用的库类的公共接口。如果你确实改变了它,无论你做什么,你都需要重新编译可执行文件。请记住几件事。
-
尝试将尽可能多的实现排除在可执行文件包含的头文件之外。更改头文件将强制重新编译,这并不总是必要的。
-
如果将类添加到共享库,则不需要重新编译可执行文件。这应该不是问题。
解决方案(如果可用(是创建 PIE 可执行文件。
测试:
g++ -fpic -pie -fpie -rdynamic -Wl,--unresolved-symbols=ignore-in-object-files -g main.cpp -o test
LD_PRELOAD=./libbase.so ./test
base function
相关文章:
- 如何定义一个纯抽象基类
- 使用子类覆盖基类中定义的函数
- 将抽象基类中的所有纯虚函数定义为 varaidaic 模板
- 使(虚拟)函数在大多数派生类中无法访问中间基类中可访问,定义良好?
- 为什么为派生类定义复制构造函数需要定义基类的默认构造函数?
- Linux c++.在预加载的共享库中定义的基类的崩溃调用函数
- 基类可以声明虚拟方法但不定义它吗?仍然在派生类中定义
- 错误:基类在从基类父派生类 Son 时未定义
- 无法使用在子类中定义的虚拟getter实现基类
- 从派生类重新定义基类中定义的结构
- 在派生类中重新定义基类的友元函数
- 继承基类,定义基类的原型方法,但从第三个对象调用子类的方法
- C++:如何在派生类中定义基类构造函数,如果基构造函数具有带有私有成员的初始化列表
- 'class'类型重定义/基类未定义
- 使用派生类成员的地址定义基类成员指针
- 派生类是否可以在类声明中定义基类数组的大小
- 错误 C2504:'ostream_withassign':未定义基类
- 关于c++中的继承,派生类是否可以在不显式定义基类的情况下从基类获得实现
- 定义基类的静态变量
- 错误 C2504:"自动售货机":未定义基类