كيف يمكنني تجاوز MALOC ()، Calloc ()، مجانا () إلخ تحت OS X؟

StackOverflow https://stackoverflow.com/questions/929893

سؤال

على افتراض أن أحدث XCode و GCC، ما هي الطريقة الصحيحة لتجاوز وظائف تخصيص الذاكرة (أعتقد المشغل الجديد / حذف كذلك). إن مخصصات ذاكرة تصحيح الأخطاء بطيئة للغاية في اللعبة، أحتاج فقط إلى بعض الإحصائيات الأساسية التي يمكنني القيام بها بنفسي بأقل تأثير.

أعرف أنها سهلة في Linux بسبب السنانير، وكان هذا تافهة بموجب Codewarrior قبل عشر سنوات عندما كتبت Heapmanager.

للأسف smartheap لم يعد لديه نسخة ماك.

لا يوجد حل صحيح

نصائح أخرى

أود استخدام مكتبة التحميل المسبق لهذه المهمة، لأنه لا يتطلب تعديل البرنامج قيد التشغيل. إذا كنت معتادا على طريقة Unix المعتادة للقيام بذلك، فهي مسألة استبدال LD_PRELOAD مع DYLD_INSERT_LIVERIES.

الخطوة الأولى هي إنشاء مكتبة مع رمز مثل هذا، ثم قم ببناءه باستخدام خيارات ربط مكتبة مشتركة منتظمة (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(), ، على أية حال.

أخيرا، قم بإعداد بيئة التشغيل لبرنامجك وإطلاقه (قد يتطلب إجراء تعديلات اعتمادا على كيفية مقابض SHELT الخاصة بك بمتغيرات البيئة):

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

يرى صفحة دليل DELLD لمزيد من المعلومات حول متغيرات بيئة الرابط الديناميكي.

هذه الطريقة عامة جميلة. هناك قيود، ومع ذلك:

  • لن تكون قادرا على تحويل مكالمات النظام المباشر
  • إذا كان التطبيق نفسه يخدعك باستخدام dlsym() لتحميل mallocعنوان، لن يتم تحويل المكالمة. إلا إذا كنت تخدعها مرة أخرى من خلال تحويلها أيضا dlsym!

ال malloc_default_zone تقنية المذكورة في http://lists.apple.com/archives/darwin-dev/2005/apr/msg00050.html يبدو أنه لا يزال يعمل، انظر على سبيل المثال http://code.google.com/p/fileview/source/browse/trunk/fileview/fv_zone.cpp؟ spec=svn354&r=354. للحصول على مثال على استخدام يبدو أنه يشبه ما تنوي.

بعد البحث كثيرا (إدراج هنا) والقضايا مع 10.7 قررت كتابة منشور مدونات حول هذا الموضوع: كيفية تعيين خطافات malloc في أسد osx

ستجد بعض الروابط الجيدة في نهاية المنشور بمزيد من المعلومات حول هذا الموضوع.

الحل الأساسي:

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.gist.github.com/monitorjbl/3dc6d62cf5514892d5ab22a59ff34861.

كملاحظات الاسم، هذا هو OSX الخاص. ومع ذلك، كنت قادرا على القيام بذلك على بيئات 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

آمل أن يساعد هذا شخص آخر في المستقبل!

إذا تم جمع الإحصائيات الأساسية التي تحتاجها في غلاف بسيط، فإن خدعة سريعة (وقذرة كيندا) هي مجرد استخدام بعض #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 () وحرة () في ملف .c الخاص بك المدرجة في المشروع، فسيقوم رابط بحل هذا الإصدار.

الآن بعد ذلك، كيف تنوي تنفيذ malloc؟

تحقق من Emery Berger's - مؤلف نهج مخصص لذاكرة الكند لاستبدال المخصص على OSX في https://github.com/emeryberger/heap-layers/blob/master/wrappers/macwrapper.cpp. (وعدد قليل من الملفات الأخرى التي يمكنك تتبع نفسك باتباعها تشمل).

هذا مكمل لإجابة أليكس، لكنني اعتقدت أن هذا المثال كان أكثر إلحاحا من استبدال النظام المقدمة مخصص.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top