سؤال

أنا أعمل على مؤشرات C++ تطبيق إفساد كومة.الأدوات المعتادة لتحديد موقع هذا الفساد يبدو أن تكون غير قابلة للتطبيق.البنايات القديمة (18 شهرا) من التعليمات البرمجية المصدر يحمل نفس السلوك كما أحدث إصدار, لذلك هذا قد حول لفترة طويلة و لم أكن لاحظت ؛ على الجانب السلبي ، المصدر دلتا لا يمكن أن تستخدم لتحديد متى علة قدم - هناك الكثير من رمز التغييرات في المخزون.

موجه تحطمها behaviuor هو توليد الإنتاجية في هذا النظام - مأخذ نقل البيانات munged في داخلي التمثيل.لدي مجموعة من اختبار البيانات التي سيتم بشكل دوري يسبب التطبيق إلى استثناء (أماكن مختلفة, أسباب مختلفة - بما في ذلك كومة الوك الفشل ، وبالتالي:تلف في كومة الذاكرة المؤقتة).

سلوك يبدو المتعلقة قوة وحدة المعالجة المركزية أو الذاكرة عرض النطاق الترددي.أكثر من كل آلة, فمن الأسهل أن تحطم.تعطيل hyper-threading النواة او ثنائي النواة الأساسية يقلل من معدل (ولكن لا القضاء) الفساد.هذا يشير إلى توقيت ذات الصلة.

الآن هنا تكمن المشكلة:
عندما تعمل تحت خفيفة الوزن التصحيح البيئة (أقول Visual Studio 98 / AKA MSVC6) كومة الفساد معقول سهلة لإنتاج عشرة أو خمسة عشر دقيقة تمر قبل أن يفشل شيء مرعب و الاستثناءات مثل alloc; عند تشغيل متطورة تصحيح البيئة (عقلانية تنقية ، VS2008/MSVC9 أو حتى تطبيق Microsoft التحقق) يصبح النظام الذاكرة-سرعة ملزمة و لا تعطل (الذاكرة-الالتزام:وحدة المعالجة المركزية هو عدم الحصول على فوق 50%, القرص الضوء على البرنامج يسير بسرعة يمكن أن صندوق طويلا 1.3G من 2G RAM).لذلك ، لدي خيار بين أن تكون قادرا على إعادة إنشاء المشكلة (ولكن ليس تحديد سبب) أو أن تكون قادرة على إيدينيفي قضية أو مشكلة لا أستطيع الإنجاب.

بلدي الحالي أفضل التخمينات أين هو التالي:

  1. الحصول بجنون grunty مربع (استبدال الحالي ديف مربع:2Gb من ذاكرة الوصول العشوائي في E6550 Core2 Duo);وهذا سيجعل من الممكن إعدادها في صورة جاهزة الحادث مما تسبب في سوء السلوك عند تشغيل قوية تصحيح البيئة ؛ أو
  2. كتابة المشغلين new و delete استخدام VirtualAlloc و VirtualProtect بمناسبة ذاكرة للقراءة فقط حالما يتم ذلك مع.تعمل تحت MSVC6 ويكون نظام التشغيل القبض على الأشرار الذين الكتابة إلى تحرير الذاكرة.نعم هذا هو علامة على اليأس:من الذي يعيد كتابة new و delete?!وأتساءل عما إذا كان هذا هو الذهاب الى جعلها بطيئة مثل تحت تنقية et al.

و لا:الشحن مع تنقية الأجهزة بنيت في ليس خيارا.

زميل فقط مشى الماضي وطلبت "تجاوز سعة مكدس?نحن الحصول على كومة تجاوزات الآن?!?"

و الآن, السؤال: كيف يمكنني تحديد موقع كومة الفاسد؟ -


تحديث:موازنة new[] و delete[] يبدو أنه قد حصلت شوطا طويلا نحو حل المشكلة.بدلا من 15mins التطبيق يذهب الآن حوالي ساعتين قبل تحطمها.ليس هناك حتى الآن.أي اقتراحات ؟ كومة الفساد مستمرا.

تحديث:بيان بناء تحت Visual Studio 2008 يبدو بشكل أفضل ؛ الحالي الشك تقع على STL تنفيذ تلك السفن مع VS98.


  1. إعادة إنشاء المشكلة. Dr Watson سوف تنتج تفريغ التي قد تكون مفيدة في إجراء مزيد من التحليل.

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

محاولة أخرى قد تستخدم WinDebug كما التصحيح أداة قوية جدا في نفس الوقت أيضا خفيفة الوزن.

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

ربما هذه الأدوات تسمح لك على الأقل الحد من مشكلة معينة المكون.

أنا لا أحمل الكثير من الأمل ، ولكن النتيجة...

و هل أنت متأكد من أن جميع مكونات المشروع الصحيح مكتبة وقت تشغيل إعدادات (C/C++ tab, مدونة جيل الفئة في مقابل 6.0 إعدادات المشروع)?

لا أنا لا, وأنا سوف تنفق بضع ساعات غدا يمر مساحة العمل (58 مشروعا في ذلك) والتحقق من أنهم جميعا تجميع و ربط مع إشارات المناسبة.


تحديث:هذا استغرق 30 ثانية.حدد جميع المشاريع في Settings مربع الحوار إلغاء تحديد حتى تجد المشروع(ق) التي لم يكن لديك الحق في إعدادات (لديهم كل الحق في إعدادات).

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

المحلول

خياري الأول سيكون مخصص كومة أداة مثل pageheap.exe.

إعادة كتابة جديدة وحذف قد تكون مفيدة, ولكن هذا لا قبض على allocs التي يرتكبها انخفاض مستوى الرمز.إذا كان هذا هو ما تريد ، من الأفضل أن التفاف على low-level alloc APIs باستخدام Microsoft الطرق الالتفافية.

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

أيضا محاولة انتقائي إيقاف المواضيع و انظر عندما/إذا كانت المشكلة يذهب بعيدا.

ماذا مكدس الاستدعاءات وغيرها تبدو في وقت الأولى استثناء ؟

نصائح أخرى

لدي نفس المشاكل في عملي (ونحن أيضا استخدام VC6 في بعض الأحيان).و ليس هناك من حل لذلك.لدي فقط بعض التلميحات:

  • حاول مع التلقائية تحطم مقالب على آلة الإنتاج (انظر عملية قلابة).تجربتي يقول الدكتورواتسون ليست مثالية عن الإغراق.
  • إزالة جميع الصيد(...) من التعليمات البرمجية الخاصة بك.فإنها كثيرا ما تخفي خطيرة الذاكرة استثناءات.
  • تحقق Windows المتقدمة التصحيح - هناك الكثير من النصائح كبيرة على مشاكل مثل لك.أنا نوصي هذا من كل قلبي.
  • إذا كنت تستخدم STL محاولة STLPort والتحقق من يبني.صالح التكرار هي الجحيم.

حظا سعيدا.مشاكل مثل لك أن تأخذ منا شهرا إلى حل.تكون على استعداد لذلك...

تشغيل التطبيق الأصلي مع ADplus -crash -pn appnename.exe عندما تكون الذاكرة قضية الملوثات العضوية الثابتة سوف تحصل على لطيفة تفريغ كبيرة.

يمكنك تحليل تفريغ لمعرفة ما موقع الذاكرة كانت تالفة.إذا كنت محظوظا الكتابة الذاكرة هي سلسلة فريدة من نوعها يمكنك معرفة من أين جاء.إذا لم تكن محظوظا, سوف تحتاج إلى حفر في win32 كومة و الشكل ما كان أصلي الذاكرة الخصائص.(كومة -x قد تساعد)

بعد أن كنت تعرف ما كان مضطربا ، يمكنك تضييق appverifier الاستخدام مع كومة الإعدادات.أييمكنك تحديد ما DLL يمكنك مراقبة ، أو ما تخصيص حجم الشاشة.

نأمل أن هذا سوف تسريع رصد ما يكفي للقبض على الجاني.

في تجربتي, لم أكن أحتاج كاملة كومة الذاكرة المؤقتة التحقق الوضعية ، ولكن قضيت الكثير من الوقت في تحليل تفريغ التعطل(s) و تصفح المصادر.

P. S: يمكنك استخدام DebugDiag لتحليل مقالب.يمكن أن نشير إلى DLL امتلاك تلف في كومة الذاكرة المؤقتة, و تعطيك أخرى مفيدة التفاصيل.

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

في ستيف ماغواير كتاب كتابة رمز الصلبة (يوصى) ، وهناك أمثلة تصحيح الأشياء التي يمكنك القيام به في هذه الإجراءات ، مثل:

  • تتبع مخصصات العثور على التسريبات
  • تخصيص الذاكرة أكثر من اللازم ووضع علامات في بداية ونهاية الذاكرة-مجانية خلال الروتينية ، يمكنك التأكد من هذه العلامات لا تزال هناك
  • memset الذاكرة مع علامة على تخصيص (للعثور على الاستخدام غير مهيأ الذاكرة) و على الحرة (للعثور على الاستخدام الحر ان الذاكرة)

هو فكرة جيدة أخرى أبدا استخدام أشياء مثل strcpy, strcat, أو sprintf -- دائما استخدام strncpy, strncat, ، snprintf.لقد كتبت الخاصة بنا الإصدارات من هذه وكذلك للتأكد من أننا لا شطب نهاية المخزن المؤقت, و هذه قد اشتعلت الكثير من المشاكل أيضا.

يجب أن نواجه هذه المشكلة مع كل وقت و تحليل ثابت.

من أجل تحليل ثابت النظر في تجميع مع PREfast (cl.exe /analyze).يكشف متطابقة delete و delete[], التجاوزان و مجموعة من المشاكل الأخرى.تكون على استعداد ، على الرغم من واد من خلال العديد من كيلو من L6 الإنذار ، خاصة إذا كان المشروع الخاص بك لا يزال لديه L4 ليست ثابتة.

PREfast المتاحة مع Visual Studio فريق النظام ، على ما يبدو, كجزء من Windows SDK.

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

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

هذا في انخفاض الذاكرة ؟ إذا كان الأمر كذلك فإنه قد يكون الجديد هو العودة NULL بدلا من رمي std::bad_alloc.كبار السن VC++ المجمعين لم تنفذ هذا.هناك مقال عن إرث الفشل في عمليات تخصيص الذاكرة تحطمها STL تطبيقات بنيت مع VC6.

حاولت البنايات القديمة ، ولكن هناك سبب لا يمكنك الاستمرار في الذهاب أبعد من ذلك في مستودع التاريخ ورؤية بالضبط عندما كان علة قدم ؟

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

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

أول عمل من شأنه أن يكون على النحو التالي:

  1. بناء الثنائيات في "إطلاق سراح" نسخة ولكن إنشاء معلومات تصحيح الملف (سوف تجد هذا الاحتمال في إعدادات المشروع).
  2. استخدم الدكتور واتسون كما defualt المصحح (DrWtsn32 -ط) على الجهاز الذي تريد إعادة إنشاء المشكلة.
  3. Repdroduce المشكلة.الدكتور واتسون سوف تنتج تفريغ التي قد تكون مفيدة في إجراء مزيد من التحليل.

محاولة أخرى قد تستخدم WinDebug كما التصحيح أداة قوية جدا في نفس الوقت أيضا خفيفة الوزن.

ربما هذه الأدوات تسمح لك على الأقل الحد من مشكلة معينة المكون.

و هل أنت متأكد من أن جميع مكونات المشروع الصحيح مكتبة وقت تشغيل إعدادات (التبويب C/C++, الجيل رمز الفئة في مقابل 6.0 إعدادات المشروع)?

لذلك من معلومات محدودة لديك, هذا يمكن أن يكون مزيج من واحد أو أكثر من الأمور:

  • سوء استخدام كومة ، أي ضعف يحرر قراءة حرة بعد كتابة بعد الحرة ، ووضع HEAP_NO_SERIALIZE العلم مع allocs وتحرر من مؤشرات ترابط متعددة على نفس كومة
  • من الذاكرة
  • رمز سيئة (أي تجاوزات المخزن المؤقت المخزن المؤقت underflows ، إلخ.)
  • "توقيت" قضايا

إذا كان أول اثنين ولكن ليس آخر ، يجب أن يكون القبض عليه حتى الآن مع أي pageheap.exe.

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

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

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

عندما كنت في اختبار مع VS2008 لك مع HeapVerifier مع الحفاظ على الذاكرة تعيين إلى "نعم" ؟ التي يمكن أن تقلل من تأثير الأداء من كومة مخصص.(بالإضافة إلى ذلك ، يجب عليك تشغيل مع التصحيح->بدء تطبيق متحقق ، ولكن كنت قد تعرف بالفعل أن.)

يمكنك أيضا محاولة التصحيح مع Windbg ومختلف الاستخدامات !كومة الأوامر.

MSN

إذا اخترت إعادة كتابة جديدة/حذف لقد فعلت هذا و بسيطة البرمجية المصدر في:

http://gandolf.homelinux.org/~smhanov/بلوق/?id=10

هذا يمسك تسرب الذاكرة و أيضا إدراج الحرس البيانات قبل وبعد كتلة الذاكرة لالتقاط تلف في كومة الذاكرة المؤقتة.يمكنك فقط الاندماج مع ذلك عن طريق وضع #include "debug.ح" في أعلى كل CPP ملف تعريف التصحيح و DEBUG_MEM.

غرايم اقتراح مخصص malloc/مجانا هو فكرة جيدة.انظر إذا كان يمكنك أن تميز بعض نمط حول الفساد أن أعطيك مقبض الرافعة المالية.

على سبيل المثال, إذا كان هو دائما في كتلة من نفس الحجم (أقول 64 بايت) ثم تغيير إعدادات malloc/مجانا الزوج دائما تخصيص 64 بايت قطع في الصفحة الخاصة بهم.عند تحرير قطعة 64 بايت ثم تعيين حماية الذاكرة بت في هذه الصفحة لمنع يقرأ wites (باستخدام VirtualQuery).ثم أي شخص يحاول الوصول إلى هذه الذاكرة سوف تولد استثناء بدلا من إفساد كومة.

هذا لا نفترض أن عدد المعلقة 64 بايت قطع معتدلة فقط أو لديك الكثير من الذاكرة إلى حرق في المربع!

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

هل تعتقد أن هذا هو شرط السباق ؟ هي مواضيع متعددة تبادل كومة واحدة?يمكنك ان تعطي كل موضوع خاص كومة مع HeapCreate ، ثم أنها يمكن تشغيل سريع مع HEAP_NO_SERIALIZE.وإلا كومة يجب أن يكون موضوع آمنة إذا كنت تستخدم متعددة الخيوط إصدار من نظام المكتبات.

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

الثانية - ل /تحليل تبديل لها في الواقع توليد غزير التحذيرات.استخدام رمز التبديل هذا في بلدي المشروع ، ما لم تم إنشاء جديد ملف الرأس التي تستخدم #pragma تحذير إلى إيقاف جميع تحذيرات إضافية التي تم إنشاؤها بواسطة /تحليل.ثم مزيد من الانخفاض في ملف تشغيل فقط تلك التحذيرات يهمني.ثم استخدام /FI مترجم التحول إلى قوة هذا الملف رأس تدرج الأولى في كل ما تبذلونه من تجميع الوحدات.هذا يجب أن تسمح لك لاستخدام /تحليل التبديل في حين السيطرة الإخراج

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