سؤال

لقد حصلت على تسرب ذاكرة في عملية البداية (PID 1) ، ما هي الخيارات التي لدي على تصحيحها؟

تعديل: اقترح لي بعض الأدوات الحقيقية لهذا ، وضع printfs يدويًا أو حساب تخصيصات الذاكرة باليد لن يؤدي إلى قطعها. أيضا إلقاء اللبأ البارز والتشويش حول هذا ليس خيارًا حقًا.

UPD1: فالغريند لا يعمل. لا يبدو أن استبدال /SBIN /init على سطر أوامر kernel مع Valgrind + Init Magic خيار لأنه يحاول الوصول إلى /proc for self for smaps ، لكن هذه غير متوفرة قبل تشغيل init.

UPD2: Dmalloc لا يعمل أيضًا (لا يجمع على الذراع).

هل كانت مفيدة؟

المحلول

سيكون حل الرجل الفقير هو مجرد تسجيل كل مكالمة malloc و free, ، ثم تمشيط من خلال السجلات وابحث عن نمط.

ld يوفر ميزة مذهلة يمكن أن تساعد هنا.

--wrap=symbol

استخدام دالة غلاف للرمز. سيتم حل أي إشارة غير محددة إلى الرمز إلى "__WRAP_SYMBOL". سيتم حل أي إشارة غير محددة إلى "__real_symbol" على الرمز.

يمكن استخدام هذا لتوفير غلاف لوظيفة النظام. يجب أن تسمى وظيفة الغلاف "__WRAP_SYMBOL". إذا كانت ترغب في استدعاء وظيفة النظام ، فيجب أن تسمي "__real_symbol".

هنا مثال تافهة:

void *
__wrap_malloc (size_t c)
{
   printf ("malloc called with %zu\n", c);
   return __real_malloc (c);
}

إذا قمت بربط التعليمات البرمجية الأخرى باستخدام هذا الملف باستخدام -WRAP Malloc ، فستقوم جميع المكالمات بـ "Malloc" باستدعاء الوظيفة "__WRAP_MALLOC" بدلاً من ذلك. ستدعو الدعوة إلى "__real_malloc" في "__WRAP_MALLOC" وظيفة "malloc" الحقيقية.

قد ترغب في توفير وظيفة "__real_malloc" أيضًا ، بحيث تنجح الروابط بدون خيار -will. إذا قمت بذلك ، يجب ألا تضع تعريف "__real_malloc" في نفس الملف مثل "__wrap_malloc" ؛ إذا قمت بذلك ، يجوز للمجمع حل المكالمة قبل أن تتاح للرابط فرصة لفها إلى "Malloc".


تحديث

فقط لتوضيح كيف يكون هذا مفيدًا.

  • أضف ملفًا مخصصًا إلى بناء Upstart.

مثله:

void*__wrap_malloc( size_t c )
{
   void *malloced = __real_malloc(c);
   /* log malloced with its associated backtrace*/
   /* something like: <malloced>: <bt-symbol-1>, <bt-symbol-2>, .. */
   return malloced
}

void __wrap_free( void* addr )
{
   /* log addr with its associated backtrace*/
   /* something like: <addr>: <bt-symbol-1>, <bt-symbol-2>, .. */
   __real_free(addr);
}
  • إعادة ترجمة مع رموز التصحيح (-g) حتى تتمكن من الحصول على بعض الظهر اللطيف. لا يزال بإمكانك التحسين (-O2/-O3) الرمز إذا كنت ترغب في ذلك.

  • ارتباط UPSTART مع الإضافية LD_FLAGS --wrap=malloc, --wrap=free.
    الآن في أي مكان مكالمات upstart malloc سيتم حل الرمز بطريقة سحرية على رمزك الجديد __wrap_malloc. بشكل جميل ، كل هذا شفاف للرمز المترجم كما يحدث في وقت الرابط.
    انها مثل رمي أو صك مع أي من الفوضى.

  • قم بتشغيل التشغيل العلوي المُعاد تشغيله كالمعتاد حتى تكون متأكدًا من حدوث تسرب.

  • انظر من خلال سجلات عدم التطابق mallocedرمل addrس.

بضع ملاحظات:

  • ال --wrap=symbol الميزة لا تعمل مع أسماء الوظائف التي هي في الواقع وحدات الماكرو. لذا احترس من #define malloc nih_malloc. هذا هو ما تحتاجه إلى استخدامه --wrap=nih_malloc و __wrap_nih_malloc في حين أن.
  • استخدم GCC's بنيت الخلفية الميزات.
  • كل هذه التغييرات تؤثر فقط على إعادة تشغيل القابلة للتنفيذ.
  • يمكنك تفريغ السجلات إلى SQLite DB بدلاً من ذلك قد يسهل العثور على Mallocs غير متطابق.
  • يمكنك أن تجعلك تقوم بتسجيل تنسيق عبارة إدراج SQL ثم فقط أدخلها في قاعدة بيانات بعد الوفاة لمزيد من التحليل.

نصائح أخرى

يمكنك أيضًا استخدام init دون تغيير ، ولكن إنشاء غلاف يعين متغير بيئة malloc_check 1 أو أعلى. سيتيح لك ذلك رؤية بعض تشخيصات تخصيص الذاكرة.

يتمثل الاختلاف في تغيير رمز مصدر Init قليلاً لتعيين هذا البيئة المتغير في وقت مبكر قبل أن يبدأ في استخدام Malloc.

يمكنك أيضًا أن AMINEK اقترحت إضافة رمز تصحيح إلى رمز مصدر init نفسه.

يمكنك توصيل تخصيص الذاكرة بنفسك عن طريق تثبيت Malloc/Free Calls ، وحساب عدد البايتات التي تخصيتها وتحرر في كل مرة.

يمكنك محاولة ربط نسختك من Upstart TCMALLOC من Google. يأتي مع بنيت مدقق كومة.

يمكن تمكين مدقق الكومة بطريقتين:

  • اضبط متغير البيئة HEAPCHECK إلى واحد من {عادي | صارمة | Draconian}.
  • تعيين HEAPCHECK إلى local وتحقق من الرمز باليد مع HeapProfileLeakChecker أشياء.

لا أعرف كيفية تعيين متغير البيئة لـ Init.

ماذا عن تشغيل PMAP على العملية وفحص ما تنمو شرائح الذاكرة. قد يمنحك هذا فكرة عما يتناول الذاكرة. القليل من البرمجة النصية يمكن أن تجعل هذه العملية تلقائيًا تقريبًا **.

** في حياة سابقة ، كتبت بالفعل نصًا سيستغرقه ن لقطات PMAP لمجموعة من عمليات التشغيل متباعدة ر ثواني. تم تغذية ناتج ذلك في البرنامج النصي Perl الذي حدد الأجزاء التي غيرت حجمها. لقد استخدمته لتحديد العديد من تسرب الذاكرة في بعض التعليمات البرمجية التجارية. [أود أن أشارك البرامج النصية ، لكنها مغطاة بموجب IP (حقوق الطبع والنشر) لصاحب العمل السابق.

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