我有一个c ++程序,它是通过JNI从java程序调用的,我想用C ++程序中的内存分配器替换Doug Lea的dlmalloc实现(IIUC这是可行的,因为新的操作符调用了malloc下面的)。我还在我的c ++程序中使用std:list和std:map,并希望这些库函数在调用" new"时也会使用dlmalloc。运营商。我试过使用LD_PRELOAD,但似乎也会导致dmalloc也会从JAVA程序调用,我不想要它。在编译时将c ++程序与libdlmalloc.so链接起来是否足以保证所有c ++库函数都使用dlmalloc?如果是这样,可以提供一个如何链接dlmalloc的示例?感谢
答案 0 :(得分:1)
如果您的程序没有调用任何分配您需要释放的内存的libc函数(例如realpath
),您可以将静态链接到dlmalloc并仔细管理导出的集合符号。如果您只导出那些由JNI接口实际调用的函数(而不是malloc
,free
等),这应该可以。
JNI API具有回调函数,这些函数将调用malloc
/ free
,这些函数将保留原始进程中的函数,但事情将保持一致,因为malloc
/ {{ 1}}实现将匹配。
但是,您应确保您的dlmalloc变体不使用free
/ brk
,仅使用sbrk
来分配操作系统,因为较旧的分配形式可能会干扰系统mmap
。
对于ELF环境中的符号管理,Ulrich Drepper's How To Write Shared Libraries的第2.2节(导出控制)是一个很好的参考。
答案 1 :(得分:0)
我不一定认为使用链接器玩游戏很糟糕,但我有另一种选择......
如果dlmalloc有一个符号不是'malloc'的库,你可以使用自己的版本覆盖全局C ++ operator new
,operator new[]
,operator delete
和operator delete[]
调用malloc和free的dlmalloc版本。
这将导致所有C ++分配都经历您的重载,包括库函数。标准保证了这种行为。但是,如果你有两个不同版本的这些重载,那么它是未指定的,它被称为。但很明显,如果标准库本身有一个版本,那么你的版本应该优先。
这不会涵盖您可能调用的任何C标准库函数。无论如何,它们仍将使用malloc
符号,如果不使用链接器玩游戏,则无法做到这一点。幸运的是,在大多数C ++程序中,标准C库的调用方式不会很多。
重新编译程序是不够的。实际上,由于new
和delete
运算符的标准C ++实现没有出现在标准库头中,所以它在很大程度上无法完成任何事情,因此预处理器无法替换{{1}使用dlmalloc库提供的任何功能。