Xcode 如何在OS X下重写malloc()、calloc()、free()等?

Xcode 如何在OS X下重写malloc()、calloc()、free()等?,xcode,macos,malloc,overriding,Xcode,Macos,Malloc,Overriding,假设使用最新的XCode和GCC,那么覆盖内存分配函数的正确方法是什么(我猜操作符new/delete也是如此)。调试内存分配器对于一个游戏来说太慢了,我只需要一些基本的统计数据,我可以用最小的影响自己完成 我知道在Linux中使用钩子很容易,而在十年前我编写HeapManager时,在codewarrior中这是微不足道的 遗憾的是,smartheap不再有mac版本。中提到的malloc\u default\u zone技术似乎仍然有效,例如,请参阅一个与您的意图类似的示例用法。如果您需要的

假设使用最新的XCode和GCC,那么覆盖内存分配函数的正确方法是什么(我猜操作符new/delete也是如此)。调试内存分配器对于一个游戏来说太慢了,我只需要一些基本的统计数据,我可以用最小的影响自己完成

我知道在Linux中使用钩子很容易,而在十年前我编写HeapManager时,在codewarrior中这是微不足道的


遗憾的是,smartheap不再有mac版本。

中提到的
malloc\u default\u zone
技术似乎仍然有效,例如,请参阅一个与您的意图类似的示例用法。

如果您需要的基本统计信息可以在一个简单的包装器中收集,请使用一个快速(而且有点脏)的技巧就是使用一些
#define
宏替换

void* _mymalloc(size_t size)
{
    void* ptr = malloc(size);

    /* do your stat work? */

    return ptr;
}


注意:如果宏是在_mymalloc定义之前定义的,那么它最终将替换该函数中的malloc调用,从而给您留下无限递归。。。因此,请确保情况并非如此。您可能希望在函数定义之前显式定义它,然后根据最终包含它的位置简单地(重新)定义它,以避免出现这种情况。

我认为如果您在项目中包含的自己的.c文件中定义malloc()和free(),链接器将解析该版本


现在,您打算如何实现malloc?

我将使用库预加载来完成此任务,因为它不需要修改正在运行的程序。如果您熟悉常用的Unix方法,那么几乎只需使用DYLD_INSERT_库替换LD_PRELOAD即可

第一步是使用这样的代码创建库,然后使用常规共享库链接选项(
gcc-dynamiclib
)构建它:

请注意,如果您还转移了
calloc()
及其实现调用
malloc()
,则可能需要额外的代码来检查如何调用您。C++程序应该非常安全,因为<代码>新< /Cuff>操作符调用<代码> MalCube()/<代码>,但请注意,没有标准强制执行。不过,我从未遇到过不使用
malloc()
的实现

最后,为您的程序设置运行环境并启动它(可能需要根据shell处理环境变量的方式进行调整):

有关动态链接器环境变量的详细信息,请参阅

这种方法非常通用。但是,也有一些限制:

  • 您将无法转接直接系统呼叫
  • 如果应用程序本身通过使用
    dlsym()
    加载
    malloc
    的地址来欺骗您,那么调用将不会被转移。但是,除非您通过转移
    dlsym
    来欺骗它!
经过大量搜索(包括这里)和10.7的问题,我决定写一篇关于这个主题的博文:

你会在文章的最后找到一些好的链接,其中有关于这个主题的更多信息

基本解决办法:

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
}
查看Emery Berger的《囤积内存分配器》一书的作者,他提出了一种在OSX上替换分配器的方法(以及一些其他文件,您可以通过以下内容来跟踪自己)


这是对Alex答案的补充,但我认为这个例子更接近于替换系统提供的分配器。

这是一个老问题,但我自己在尝试这样做时遇到了它。我对我正在进行的一个个人项目中的这个话题感到好奇,主要是为了确保我认为自动释放的东西被正确地释放。最后,我写了一个C++实现,让我跟踪分配的堆的数量,如果我选择的话,报告它。p>

顾名思义,这是OSX特有的。但是,我可以在Linux环境中使用
malloc\u-available\u-size

示例

#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);
}
建筑

$ 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

希望这有助于其他人在未来

这不能用C++运算符new /Delphi或没有源代码的库来操作,因为我为操作员找到了新的,非常好,现在来想一下MalOC/CalOthTy是一个很好的例子,但是我认为一个更干净的例子,完全替代了OSX的内存分配器。还是。。。原始的电子邮件线程非常棒。:)注册一个新的默认区域是可行的,但如果你只需要一些“基本的统计数据”,这有时会太多,就像问题所指出的那样。进入默认区域更容易,但它不再像Alex所描述的那样起作用。那么,为什么对一个只帮助解决问题的答案投反对票而不发表任何评论呢?
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
}
#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);
}
$ 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