سؤال

لدي تطبيق رمز C واحد. الذي كنت أبنيه باستخدام MS-VS2005. كان لدي مخزن مؤقت لبيانات الإخراج والذي تم تخصيصه ديناميكيًا باستخدام Malloc.

بالنسبة لبعض حالات الاختبار ، كان حجم الذاكرة الذي كان يجري malloc'd يتراجع عن حجم الإخراج الفعلي في البايتات التي تم إنشاؤها. تم كتابة هذا الناتج الأكبر حجمًا في المخزن المؤقت الأصغر حجمًا مما تسبب في تجاوز المخزن المؤقت. كنتيجة لذلك تم تحطيم اختبار الاختبار مع عرض MSVS-2005 على نافذة "فساد كومة ...."

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

سؤالي هو:

1.) ما هي الأدوات التي يمكنني استخدامها للكشف عن شروط التدفق المفرط في الذاكرة الديناميكية هذه. هل يمكن أن تساعد أيضًا في اكتشاف أي شروط في التدفق المخزن المؤقت (بغض النظر عما إذا كان المخزن المؤقت/الصفيف على كومة ، مكدس ، منطقة الذاكرة العالمية)؟

2.) هل ستساعد أدوات تسرب الذاكرة (مثل Say Purify) أو أدوات تحليل التعليمات البرمجية مثل Lint ، Klocworks كانت ستساعد في حالة معينة؟ أعتقد أنهم يجب أن يكونوا أدوات تحليل وقت التشغيل.

شكرًا لك.

-ميلادي.

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

المحلول

حل واحد ، واجهته لأول مرة في الكتاب كتابة رمز صلب, ، هو "لف" malloc() API مع رمز التشخيص.

أولا ، التشخيص malloc() يرتب لتخصيص بايت إضافية لبطانة زائدة. على سبيل المثال ، يتم حجز أربعة بايت إضافية بعد الذاكرة المخصصة وتحتوي على الأحرف "غرامة".

في وقت لاحق ، عندما المؤشر من malloc() يتم تمريره إلى free(), ، نسخة تشخيصية مماثلة من free() يسمى. قبل استدعاء التنفيذ القياسي لـ free() والتخلي عن الذاكرة ، يتم التحقق من الحارس الخلفي ؛ يجب أن يكون غير معدّل. إذا تم تعديل الحارس ، فقد تم إساءة استخدام مؤشر الكتلة في وقت ما بعد إرجاعه من التشخيص malloc().

هناك مزايا لاستخدام صفحة واقي حماية الذاكرة بدلاً من نمط الحارس للكشف عن تدفقات المخزن المؤقت. على وجه الخصوص ، مع طريقة قائمة على الأنماط ، يتم اكتشاف الوصول غير القانوني للذاكرة إلا بعد الحقيقة. يتم اكتشاف الكتابة غير القانونية فقط بواسطة طريقة نمط الحارس. تلتقط طريقة حماية الذاكرة القراءات والكتابة غير القانونية ، ويتم اكتشافها فورًا عند حدوثها.

وظائف التفاف التشخيصية ل malloc() يمكن أيضًا معالجة سوء الاستخدام الآخر من malloc(), ، مثل المكالمات المتعددة ل free() لنفس كتلة الذاكرة. ايضا، realloc() يمكن تعديلها لتحريك الكتل دائمًا عند تنفيذها في بيئة تصحيح الأخطاء ، لاختبار المتصلين realloc().

على وجه الخصوص ، قد تسجل الأغلفة التشخيصية جميع الكتل المخصصة والتحرير ، والتقرير عن تسرب الذاكرة عندما يخرج البرنامج. تسرب الذاكرة هي كتل يتم تخصيصها من خلال عدم تحريرها أثناء تنفيذ البرنامج.

عند لف malloc() API ، يجب على المرء أن يلف جميع الوظائف ذات الصلة ، بما في ذلك calloc(), realloc(), و strdup().

الطريقة النموذجية لالتفاف هذه الوظائف هي عبر وحدات الماكرو قبل المعالج:

#define malloc(s)   diagnostic_malloc(s, __FILE__, __LINE__)
/* etc.... */

إذا نشأت الحاجة إلى ترميز مكالمة إلى التنفيذ القياسي (على سبيل المثال ، سيتم تمرير الكتلة المخصصة إلى مكتبة ثالثة ثنائية تتوقع تحرير الكتلة باستخدام المعيار free() التنفيذ ، يمكن الوصول إلى أسماء الوظائف الأصلية بدلاً من الماكرو المسبق باستخدام (malloc)(s) - أي مكان الأقواس حول اسم الوظيفة.

نصائح أخرى

شيء يمكنك تجربته هو تخصيص صفحات كافية + 1 باستخدام VirtualAlloc ، استخدم VirtualProtect مع page_readonly | Page_Guard أعلام على الصفحة الأخيرة ، ثم قم بمحاذاة التخصيص المشتبه به بحيث تكون نهاية الكائن بالقرب من بداية الصفحة المحمية. إذا سارت الأمور على ما يرام ، فيجب أن تحصل على انتهاك للوصول عند الوصول إلى صفحة الحراسة. يساعد إذا كنت تعرف ما يقرب من التخصيص. وإلا فإنه يتطلب تجاوز جميع المخصصات التي قد تتطلب الكثير من الذاكرة الإضافية (على الأقل صفحتين لكل تخصيص). هناك اختلاف في هذه التقنية التي أعمدها بموجب هذا "حارس الصفحة الإحصائي" هو تخصيص الذاكرة بشكل عشوائي فقط لنسبة مئوية صغيرة نسبيًا من المخصصات بهذه الطريقة لتجنب الانتفاخات الكبيرة للأشياء الصغيرة. على عدد كبير من عمليات التنفيذ ، يجب أن تكون قادرًا على ضرب الخطأ. يجب أن يكون مولد الأرقام العشوائية صياغة شيء مثل الوقت في هذه الحالة. وبالمثل ، يمكنك تخصيص صفحة الحراسة أمام الكائن إذا كنت تشك في الكتابة فوقها في عنوان أقل (لا يمكنك القيام بها في نفس الوقت ولكن من الممكن خلطها بشكل عشوائي أيضًا).

تحديث: اتضح أن gflags.exe (تستخدم ليكون pageHeap.exe) تدعم الأداة المساعدة Microsoft بالفعل "واقي الصفحة الإحصائي" لذلك أعيد اختراع العجلة :) كل ما عليك فعله هو تشغيل gflags.exe /p /تمكين [ / عشوائي 0-100] yoursapplication.exe وقم بتشغيل التطبيق الخاص بك. إذا كنت تستخدم كومة مخصصة أو حراس مخصصين على تخصيصات الكومة الخاصة بك ، فيمكنك ببساطة التبديل إلى استخدام Heapalloc على الأقل لالتقاط الأخطاء ثم العودة. Gflags.exe هي جزء من حزمة أدوات الدعم ويمكن تنزيلها من مركز تنزيل Microsoft ، ما عليك سوى إجراء بحث هناك.

يمكن أن يصطاد PC-Lint بعض أشكال مشكلات Malloc/New Size ، لكنني لست متأكدًا مما إذا كان سيجد لك.

يحتوي VS2005 على فحص فائض عازلة جيد لكائنات المكدس في وضع التصحيح (يعمل في نهاية الوظيفة). وهو فحص دوري للكومة.

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

عملية مؤلمة ، لذلك أنا حريص على تعلم طرق أفضل أيضًا.

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

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