簡體   English   中英

如何在OS X下覆蓋malloc(),calloc(),free()等?

[英]how can i override malloc(), calloc(), free() etc under OS X?

假設最新的XCode和GCC,覆蓋內存分配函數的正確方法是什么(我猜運算符new / delete也是如此)。 調試內存分配器對於游戲來說太慢了,我只需要一些基本的統計數據,我可以自己做,影響最小。

我知道它在Linux中很容易因為鈎子而存在,而且在十年前編寫HeapManager時,這在codewarrior下是微不足道的。

可悲的是,smartheap不再有mac版本。

我會使用庫預加載來完成此任務,因為它不需要修改正在運行的程序。 如果您熟悉通常的Unix方法,那么幾乎就是用DYLD_INSERT_LIBRARIES替換LD_PRELOAD。

第一步是使用這樣的代碼創建一個庫,然后使用常規的共享庫鏈接選項( 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欺騙它!

http://lists.apple.com/archives/darwin-dev/2005/Apr/msg00050.html中提到的malloc_default_zone技術似乎仍然有效,請參閱http://code.google.com/p/fileview/source /browse/trunk/fileview/fv_zone.cpp?spec=svn354&r=354示例用法似乎與您想要的類似。

這是一個老問題,但我在嘗試自己做的時候偶然發現了這個問題。 我對我正在處理的個人項目感到好奇,主要是為了確保我認為自動解除分配的內容正在被正確解除分配。 我最后編寫了一個C ++實現,允許我跟蹤分配的堆量並在我選擇時報告它。

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

顧名思義,這是OSX特有的。 但是,我能夠使用malloc_usable_size在Linux環境中執行此malloc_usable_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

希望這有助於將來的其他人!

經過大量搜索(包括此處)和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
}

查看Emery Berger - 作為Hoard內存分配器的作者 - 在OSX上替換分配器的方法,請訪問https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp (以及一些您可以通過以下內容跟蹤自己的其他文件)。

這是對Alex的回答的補充,但我認為這個例子更像是取代系統提供的分配器。

如果您需要的基本統計數據可以在一個簡單的包裝器中收集,那么快速(而且有點臟)的技巧就是使用一些#define宏替換。

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

    /* do your stat work? */

    return ptr;
}

#define malloc(sz_) _mymalloc(sz_)

the _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. 注意 :如果宏在_mymalloc定義定義,它將最終替換該函數內的malloc調用,使您無限遞歸...所以請確保不是這種情況。 您可能希望在該函數定義之前顯式#undef它,然后根據您最終包含它的位置簡單地(重新)定義它以希望避免這種情況。

我想如果在項​​目中包含的自己的.c文件中定義malloc()和free(),鏈接器將解析該版本。

那么,你打算如何實現malloc?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM