在为服务器编写共享库时,我陷入了以下情况。
为了便于理解:
- 让我们将服务器框架称为 fwA
- 我写的共享库 libB
- 由 fwA 和 libB 链接的不同版本的库,分别命名为 libC1 和 libC2
fwA 通过 dllopen 加载 libB
以下是我的问题: libC 中定义了一个数据结构(DS1),但是,在 libC1 和 libC2 中,数据结构略有不同。
编译器/链接器/程序如何确定他们将使用哪个版本的数据结构?
在为服务器编写共享库时,我陷入了以下情况。
为了便于理解:
fwA 通过 dllopen 加载 libB
以下是我的问题: libC 中定义了一个数据结构(DS1),但是,在 libC1 和 libC2 中,数据结构略有不同。
编译器/链接器/程序如何确定他们将使用哪个版本的数据结构?
数据结构不是对象,因此链接器不会直接看到它们。每个库都将采用它们的布局。
如果数据结构的实际实例没有在不同版本之间共享,这可以工作。例如,在您的场景中,只要 fwA 和 libB 之间没有传递此类结构,您就可以了。fwA 和 libC1 之间的通信是安全的,libB 和 libC2 也是如此。
Windows 世界一直在这样做:每个 DLL 调用malloc
并free
链接到特定版本的 C 运行时,甚至可能使用内联函数来访问分配器数据结构。
只要分配对象的 DLL 也负责释放它,这是完全可以接受的。因此,如果您的图书馆有
foo *alloc_foo() { return (foo *)malloc(sizeof(foo)); }
那么调用接收到的指针是不安全的,free(my_foo);
因为 DLL 可能正在使用不同的分配器实现。相反,使用他们提供的
void free_foo(foo *fp) { free(fp); }
因此,fwA 和 libB 之间的接口应该设计成不依赖于 libC ABI,否则 libC ABI 也会成为 libB ABI 的一部分。
如果结构定义在libC1
and中不同libC2
,那么它肯定会在某个地方访问错误的偏移量。其未定义的行为。我们不应该这样使用。