xcode 如何在 OS X 下覆盖 malloc()、calloc()、free() 等?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/929893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how can i override malloc(), calloc(), free() etc under OS X?
提问by
Assuming the latest XCode and GCC, what is the proper way to override the memory allocation functions (I guess operator new/delete as well). The debugging memory allocators are too slow for a game, I just need some basic stats I can do myself with minimal impact.
假设最新的 XCode 和 GCC,覆盖内存分配函数的正确方法是什么(我猜也是 operator new/delete)。调试内存分配器对于游戏来说太慢了,我只需要一些基本的统计数据,我可以在最小的影响下自己完成。
I know its easy in Linux due to the hooks, and this was trivial under codewarrior ten years ago when I wrote HeapManager.
由于钩子,我知道它在 Linux 中很容易,十年前当我编写 HeapManager 时,这在 codewarrior 下是微不足道的。
Sadly smartheap no longer has a mac version.
遗憾的是 smartheap 不再有 mac 版本。
回答by sam hocevar
I would use library preloading for this task, because it does not require modification of the running program. If you're familiar with the usual Unix way to do this, it's almost a matter of replacing LD_PRELOAD with DYLD_INSERT_LIBRARIES.
我会为此任务使用库预加载,因为它不需要修改正在运行的程序。如果您熟悉执行此操作的常用 Unix 方式,那么几乎可以用 DYLD_INSERT_LIBRARIES 替换 LD_PRELOAD。
First step is to create a library with code such as this, then build it using regular shared library linking options (gcc -dynamiclib
):
第一步是使用这样的代码创建一个库,然后使用常规共享库链接选项 ( gcc -dynamiclib
)构建它:
void *malloc(size_t size)
{
void * (*real_malloc)(size_t);
real_malloc = dlsym(RTLD_NEXT, "malloc");
fprintf(stderr, "allocating %lu bytes\n", (unsigned long)size);
/* Do your stuff here */
return real_malloc(size);
}
Note that if you also divert calloc()
and its implementation calls malloc()
, you may need additional code to check how you're being called. C++ programs should be pretty safe because the new
operator calls malloc()
anyway, but be aware that no standard enforces that. I have never encountered an implementation that didn't use malloc()
, though.
请注意,如果您还转移calloc()
及其实现调用malloc()
,您可能需要额外的代码来检查您是如何被调用的。C++ 程序应该非常安全,因为无论如何new
操作符都会调用malloc()
,但要注意没有标准强制执行这一点。不过,我从未遇到过不使用 的实现malloc()
。
Finally, set up the running environment for your program and launch it (might require adjustments depending on how your shell handles environment variables):
最后,为您的程序设置运行环境并启动它(可能需要根据您的 shell 处理环境变量的方式进行调整):
export DYLD_INSERT_LIBRARIES=./yourlibrary.dylib
export DYLD_FORCE_FLAT_NAMESPACE=1
yourprogram --yourargs
See the dyld manual pagefor more information about the dynamic linker environment variables.
有关动态链接器环境变量的更多信息,请参阅dyld 手册页。
This method is pretty generic. There are limitations, however:
这种方法非常通用。但是也有限制:
- You won't be able to divert direct system calls
- If the application itself tricks you by using
dlsym()
to loadmalloc
's address, the call won't be diverted. Unless, however, you trick it back by also divertingdlsym
!
- 您将无法转移直接系统调用
- 如果应用程序本身通过使用
dlsym()
加载malloc
的地址来欺骗您,则不会转移呼叫。但是,除非您还通过转移来欺骗它dlsym
!
回答by Alex Martelli
The malloc_default_zone
technique mentioned at http://lists.apple.com/archives/darwin-dev/2005/Apr/msg00050.htmlappears to still work, see e.g. http://code.google.com/p/fileview/source/browse/trunk/fileview/fv_zone.cpp?spec=svn354&r=354for an example use that seems to be similar to what you intend.
http://lists.apple.com/archives/darwin-dev/2005/Apr/msg00050.html中malloc_default_zone
提到的技术似乎仍然有效,例如参见http://code.google.com/p/fileview/source/浏览/trunk/fileview/fv_zone.cpp?spec=svn354&r=354的示例用途似乎与您的意图相似。
回答by bkdc
After much searching (here included) and issues with 10.7 I decided to write a blog post about this topic: How to set malloc hooks in OSX Lion
经过大量搜索(此处包括)和 10.7 的问题后,我决定写一篇关于这个主题的博客文章:如何在 OSX Lion 中设置 malloc 钩子
You'll find a few good links at the end of the post with more information on this topic.
您会在文章末尾找到一些很好的链接,其中包含有关此主题的更多信息。
The basic solution:
基本解决方案:
malloc_zone_t *dz=malloc_default_zone();
if(dz->version>=8)
{
vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);//remove the write protection
}
original_free=dz->free;
dz->free=&my_free; //this line is throwing a bad ptr exception without calling vm_protect first
if(dz->version==8)
{
vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);//put the write protection back
}
回答by monitorjbl
This is an old question, but I came across it while trying to do this myself. I got curious about this topic for a personal project I was working on, mainly to make sure that what I thought was automatically deallocated was being properly deallocated. I ended up writing a C++ implementation to allow me to track the amount of allocated heap and report it out if I so chose.
这是一个老问题,但我在尝试自己做这件事时遇到了它。我对我正在从事的个人项目的这个主题感到好奇,主要是为了确保我认为自动释放的内容被正确释放。我最终编写了一个 C++ 实现,以允许我跟踪分配的堆的数量并在我选择时报告出来。
https://gist.github.com/monitorjbl/3dc6d62cf5514892d5ab22a59ff34861
https://gist.github.com/monitorjbl/3dc6d62cf5514892d5ab22a59ff34861
As the name notes, this is OSX-specific. However, I was able to do this on Linux environments using the malloc_usable_size
顾名思义,这是特定于 OSX 的。但是,我能够在 Linux 环境中使用malloc_usable_size
Example
例子
#define MALLOC_DEBUG_OUTPUT
#include "malloc_override_osx.hpp"
int main(){
int* ip = (int*)malloc(sizeof(int));
double* dp = (double*)malloc(sizeof(double));
free(ip);
free(dp);
}
Building
建筑
$ clang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk \
-pipe -stdlib=libc++ -std=gnu++11 -g -o test test.cpp
$ ./test
0x7fa28a403230 -> malloc(16) -> 16
0x7fa28a403240 -> malloc(16) -> 32
0x7fa28a403230 -> free(16) -> 16
0x7fa28a403240 -> free(16) -> 0
Hope this helps someone else out in the future!
希望这可以帮助其他人在未来!
回答by sholsapp
Check out Emery Berger's -- the author of the Hoard memory allocator's -- approach for replacing the allocator on OSX at https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp(and a few other files you can trace yourself by following the includes).
在https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp(和一些您可以通过遵循包含来跟踪自己的其他文件)。
This is complementary to Alex's answer, but I thought this example was more to-the-point of replacing the system provided allocator.
这是对 Alex 回答的补充,但我认为这个例子更接近于替换系统提供的分配器。
回答by sholsapp
If the basic stats you need can be collected in a simple wrapper, a quick (and kinda dirty) trick is just using some #define
macro replacement.
如果您需要的基本统计信息可以收集在一个简单的包装器中,那么一个快速(而且有点脏)的技巧就是使用一些#define
宏替换。
void* _mymalloc(size_t size)
{
void* ptr = malloc(size);
/* do your stat work? */
return ptr;
}
and
和
#define malloc(sz_) _mymalloc(sz_)
Note: if the macro is defined beforethe _mymalloc definition it will end up replacing the malloc call inside that function leaving you with infinite recursion... so ensure this isn't the case. You might want to explicitly #undef
it before that function definition and simply (re)define it afterward depending on where you end up including it to hopefully avoid this situation.
注意:如果宏是在_mymalloc 定义之前定义的,它将最终替换该函数内的 malloc 调用,从而使您具有无限递归......所以确保不是这种情况。您可能希望#undef
在该函数定义之前显式地定义它,然后根据最终包含它的位置简单地(重新)定义它以希望避免这种情况。
回答by Joshua
I think if you define a malloc() and free() in your own .c file included in the project the linker will resolve that version.
我认为如果您在包含在项目中的自己的 .c 文件中定义 malloc() 和 free() ,链接器将解析该版本。
Now then, how do you intend to implement malloc?
那么,你打算如何实现 malloc 呢?