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

由于钩子,我知道它在 Linux 中很容易,十年前当我编写 HeapManager 时,这在 codewarrior 下是微不足道的。

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

没有正确的解决方案

其他提示

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

第一步是使用此类代码创建一个库,然后使用常规共享库链接选项构建它(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);
}

请注意,如果您还转移 calloc() 及其实现调用 malloc(), ,您可能需要额外的代码来检查您的呼叫方式。C++ 程序应该非常安全,因为 new 接线员呼叫 malloc() 无论如何,但请注意,没有标准强制执行这一点。我从未遇到过不使用的实现 malloc(), , 尽管。

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

export DYLD_INSERT_LIBRARIES=./yourlibrary.dylib
export DYLD_FORCE_FLAT_NAMESPACE=1
yourprogram --yourargs

dyld 手册页 有关动态链接器环境变量的更多信息。

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

  • 您将无法转移直接系统调用
  • 如果应用程序本身通过使用来欺骗您 dlsym() 加载 malloc的地址,呼叫不会被转移。然而,除非你也通过转移来欺骗它 dlsym!

经过大量搜索(包括这里)和 10.7 的问题后,我决定写一篇关于这个主题的博客文章: 如何在 OSX Lion 中设置 malloc 挂钩

您会在文章末尾找到一些很好的链接,其中包含有关此主题的更多信息。

基本解决方案:

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
}

这是一个老问题,但我碰到它同时试图做这自己。我好奇这个话题一个个人项目我工作,主要是为了确保我以为是自动释放了被正确释放。我结束了编写C ++实现,让我跟踪分配的堆量和报告出来,如果我这样选择。

https://gist.github.com/monitorjbl/3dc6d62cf5514892d5ab22a59ff34861

作为名称的音符,这是OSX特定的。不过,我能做到这一点上使用malloc_usable_size

Linux环境

示例

#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

希望这有助于别人出未来!

如果您需要的基本统计数据可以在一个简单的包装器中收集,那么一个快速(有点肮脏)的技巧就是使用一些 #define 宏替换。

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

    /* do your stat work? */

    return ptr;
}

#define malloc(sz_) _mymalloc(sz_)

笔记: :如果定义了宏 _mymalloc 定义最终将替换该函数内的 malloc 调用,从而使您陷入无限递归......因此请确保情况并非如此。你可能想明确地 #undef 它位于该函数定义之前,并在之后简单地(重新)定义它,具体取决于您最终包含它的位置,以期避免这种情况。

我觉得如果你定义的malloc()和free()在自己的.c文件包含在项目中连接器将解决该版本。

现在那么,你怎么打算实施的malloc?

查看 Emery Berger(Hoard 内存分配器的作者)在 OSX 上替换分配器的方法,网址为: https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp (以及您可以通过以下包含内容自行跟踪的其他一些文件)。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top