我想编写一个共享库,以便可以将其内存使用情况与链接的应用程序隔离开来。也就是说,如果共享库,我们称之为libmemory.so
,调用malloc
,我想将该内存维护在与用于为应用程序中malloc
调用提供服务的堆不同的堆中。这个问题不是关于编写内存分配器,而是关于链接和加载库和应用程序。
到目前为止,我一直在尝试函数插入、符号可见性和链接技巧的组合。到目前为止,我无法做到这一点,因为一件事:标准库。我找不到一种方法来区分对内部使用的标准库的调用malloc
发生在libmemory.so
与应用程序中。这会导致一个问题,因为libmemory.so
内的任何标准库使用都会污染应用程序堆。
我目前的策略是将共享库中malloc
的定义作为隐藏符号插入。这工作得很好,所有库代码都按预期工作,当然,除了在运行时动态加载的标准库。当然,我一直在尝试找到一种方法来静态嵌入标准库用法,以便它在编译时使用libmemory.so
中的插入malloc
。我尝试过-static-libgcc
和-static-libstdc++
但没有成功(无论如何,这似乎不鼓励)。这是正确的答案吗?
怎么办?
附言,进一步阅读总是不胜感激的,在问题标记方面提供帮助会很好。
我尝试过-static-libgcc和-static-libstdc++但没有成功
当然,这不会成功:malloc
不住在libgcc
或libstdc++
,而是住在libc
。
您要做的是将libmemory.so
与一些替代malloc
实现(例如 tcmalloc 或 jemalloc)静态链接,并隐藏所有malloc
符号。然后,您的库和应用程序将具有绝对独立的堆。
不言而喻,您永远不能在库中分配某些内容并在应用程序中释放它,反之亦然。
理论上你也可以将系统libc.a
的malloc
部分链接到你的库中,但实际上GLIBC(以及大多数其他UNIX C库)不支持部分静态链接(如果你链接libc.a
,你一定不能链接libc.so
)。
更新:
如果 libmemory.so 使用动态链接的标准库函数,例如gmtime_r,从而在运行时解析malloc,那么 libmemory.so 错误地使用了运行时提供的malloc(显然来自glibc
这没有错。由于您已将malloc
隐藏在库中,因此gmtime_r
无法使用其他malloc
。
此外,除了 GLIBC 本身的内部使用外,gmtime_r
不会分配内存,并且此类内存可以通过 __libc_freeres
清理,因此在使用 GLIBC 的malloc
之外的任何地方分配此内存都是错误的。
现在,fopen
是您使用的另一个示例,fopen
确实malloc
内存。显然,您希望fopen
在库调用时调用malloc
(即使fopen
不可见),但在应用程序调用时调用系统malloc
。但是fopen
怎么知道是谁叫的呢?当然,您不是建议fopen
走过堆栈来确定它是由您的库调用还是由其他东西调用?
因此,如果您真的想让您的库永远不会调用系统 malloc
,那么您必须静态链接您使用的所有其他 libc 函数,这些函数可能会调用malloc
(并将它们隐藏在您的库中)。
您可以使用类似uclibc
或dietlibc
之类的东西来实现这一点。