سؤال

في .صافي منظور:

  • ما هو تسرب الذاكرة?
  • كيف يمكنك تحديد ما إذا كان التطبيق الخاص بك التسريبات ؟ ما هي الآثار ؟
  • كيف يمكنك منع تسرب للذاكرة
  • إذا كان التطبيق الخاص بك قد تسرب الذاكرة ، أنها لا تذهب بعيدا عندما يتم إنهاء العملية أو قتل ؟ أو تسرب الذاكرة في التطبيق الخاص بك تؤثر على عمليات أخرى على النظام حتى بعد عملية الانتهاء ؟
  • و ماذا عن التعليمات البرمجية غير المدارة الوصول إليها عبر COM إمكانية التشغيل المتداخل و/أو P/استدعاء?
هل كانت مفيدة؟

المحلول

أفضل شرح رأيت في الفصل 7 من الحرة أسس البرمجة e-book.

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

عليك أن تعرف أن لديك تسرب عند البدء في الحصول على OutOfMemoryExceptions أو استخدام الذاكرة الخاصة بك يذهب أبعد من ما كنت تتوقع (PerfMon وقد لطيفة الذاكرة عدادات).

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

بالطبع ذاكرة جيدة الشخصي سوف تتيح لك رؤية وجوه الخاص بك والرسوم البيانية استكشاف التعشيش/الرجوع من الأشياء الخاصة بك لنرى أين إشارات تأتي من الجذر كائن عن (الأحمر-بوابة النمل الشخصي, JetBrains dotMemory, memprofiler حقا خيارات جيدة, أو يمكنك استخدام النص فقط WinDbg و SOS, ولكن أود أن أوصي بشدة التجارية/المنتج البصرية إلا إذا كنت المعلم الحقيقي).

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

نصائح أخرى

بالمعنى الدقيق للكلمة, تسرب الذاكرة تستهلك الذاكرة "لم تعد تستخدم" من قبل البرنامج.

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

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

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

معظم التسريبات ، الموارد يتم استردادها عندما يتم إنهاء عملية ، ولكن بعض الموارد ليست دائما تعافى في بعض الدقيق الحالات ، GDI المؤشر مقابض سيئة السمعة ذلك.بالطبع, إذا كان لديك interprocess آلية الذاكرة المخصصة في عملية أخرى لن يتحرر حتى أن عملية تحرر أو إنهاء.

أعتقد أن "ما تسرب الذاكرة" و "ما هي الآثار" الأسئلة تم الرد عليها بشكل جيد بالفعل ، ولكن أردت أن أضيف بعض الأشياء على الأسئلة الأخرى...

كيف نفهم ما إذا كان التطبيق الخاص بك التسريبات

طريقة مثيرة للاهتمام هو فتح perfmon وإضافة آثار على # بايت في كل أكوام و # Gen 2 مجموعات في كل حالة تبحث فقط في العملية الخاصة بك.إن ممارسة ميزة خاصة أسباب بايت إجمالي الزيادة ، و أن الذاكرة لا تزال تخصيص بعد القادم Gen 2 جمع يمكنك القول أن الميزة تسرب الذاكرة.

كيفية منع

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

لا تسرب تذهب بعيدا عندما يتم إنهاء العملية و ماذا عن interop COM ؟

عند إنهاء العملية ، كل تعيين الذاكرة في مساحة العنوان المستصلحة من قبل نظام التشغيل ، بما في ذلك أي كائنات COM يقدم من DLLs.نسبيا نادرا ، كائنات COM يمكن أن تقدم من عمليات منفصلة.في هذه الحالة, عند إنهاء العملية ، قد يكون لا يزال المسؤولة عن الذاكرة المخصصة في أي ملقم COM العمليات التي يمكنك استخدامها.

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

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

وأود أيضا أن تحاول التأكد مما يلي:

أ) كل شيء أن تنفذ Idisposable يتم التخلص منها إما باستخدام أخيرا كتلة أو العبارة باستخدام وتشمل هذه الفرش والأقلام وما إلى ذلك.(بعض الناس يقولون لوضع كل شيء إلى لا شيء في ذلك)

ب)علاقة وثيقة طريقة إغلاق مرة أخرى باستخدام أخيرا أو باستخدام عبارة (على الرغم من أنني قد وجدت باستخدام لا دائما قريبة اعتمادا إذا أعلن الكائن خارج باستخدام البيان)

ج)إذا كنت تستخدم التعليمات البرمجية غير المدارة/windows API التي يتم التعامل مع بشكل صحيح بعد.(بعض تنظيف الطرق من أجل الإفراج عن الموارد)

ويساعد هذا الأمل.

إذا كنت بحاجة إلى تشخيص تسرب الذاكرة في .صافي تحقق هذه الروابط:

http://msdn.microsoft.com/en-us/magazine/cc163833.aspx

http://msdn.microsoft.com/en-us/magazine/cc164138.aspx

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

مايكروسوفت لديها أيضا أحدث أداة للمساعدة في توليد تفريغ تعطل محل ADPlus ، ودعا DebugDiag.

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

باستخدام CLR التعريف من مايكروسوفت http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en هو وسيلة رائعة لتحديد الكائنات التي تحتجز الذاكرة ، ما تدفق التنفيذ يؤدي إلى خلق هذه الكائنات ، ورصد الكائنات التي تعيش فيها على كومة (تجزئة ، لوه ، إلخ.).

أفضل شرح كيفية جمع القمامة يعمل في جيف Richters CLR عن طريق C# كتاب (Ch.20).قراءة هذا يعطي عظيم أسس لفهم كيفية الكائنات لا تزال قائمة.

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

على سبيل المثال

SomeExternalClass.Changed += new EventHandler(HandleIt);

وننسى أن أخلع عليه عند التصرف ، ثم SomeExternalClass لديه المرجع إلى صفك.

كما ذكر أعلاه ، سايتك الذاكرة التعريف ممتاز في عرض جذور الأشياء كنت تشك في تسرب.

ولكن هناك أيضا طريقة سريعة جدا للتحقق من نوع معين هو مجرد استخدام WnDBG (حتى يمكنك استخدام هذا في VS.NET الإطار الحالي في حين المرفقة):

.loadby sos mscorwks
!dumpheap -stat -type <TypeName>

الآن تفعل شيئا تعتقد أنه سوف تتخلص كائنات من هذا النوع (على سبيل المثالإغلاق النافذة).إنه مفيد هنا أن يكون التصحيح زر في مكان ما أن سيتم تشغيل System.GC.Collect() بضع مرات.

ثم تشغيل !dumpheap -stat -type <TypeName> مرة أخرى.إذا كان عدد لا تذهب أو لا تذهب إلى أسفل كما كنت تتوقع ، ثم يكون لديك أساس لمزيد من التحقيق.(أنا حصلت هذا غيض من ندوة قدمها Ingo الدك).

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

لماذا الناس يعتقدون أن تسرب الذاكرة في .صافي غير نفس أي تسرب ؟

تسرب الذاكرة عندما نعلق على الموارد وعدم السماح لها الذهاب.يمكنك القيام بذلك على حد سواء في إدارة في غير المدارة الترميز.

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

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

عندما الترميز غير المدارة, كنت عادة تأكد من تنظيف تعلم أن الموارد كنت تأخذ عقد من سيكون مسؤولية لتنظيف ليس البواب.

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

في إدارتها حيث سوف أضع رقبتي على الخط القول أنها لا تذهب بعيدا مرة واحدة عملية قتل/إزالة.

أرى الكثير من الناس لديهم هذا على الرغم من, وأنا آمل حقا أن هذا سينتهي.لا يمكنك أن تطلب من المستخدم إنهاء التطبيق الخاص بك لتنظيف الفوضى!نلقي نظرة على متصفح, التي يمكن أن تكون أي ، و و الخ, ثم فتح, يقول, Google Reader, السماح لها بالبقاء لعدة أيام, و ننظر إلى ما يحدث.

إذا كنت ثم فتح آخر علامة تبويب في المتصفح, تصفح بعض المواقع ، ثم إغلاق علامة التبويب التي استضافت الصفحة الأخرى التي جعلت المتصفح تسرب هل تعتقد المتصفح سيتم الإفراج عن الذاكرة ؟ ولا حتى مع أي.على جهاز الكمبيوتر IE سوف تأكل بسهولة 1 بنك الخليج الدولي من ذاكرة في فترة قصيرة من الوقت (حوالي 3-4 أيام) إذا كنت تستخدم قارئ جوجل.بعض newspages هي أسوأ من ذلك.

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

الاطلاق.أيضا, لا تستخدم .Dispose() الأسلوب على الأشياء يمكن التخلص منها عند الاقتضاء يمكن أن يسبب mem التسريبات.أسهل طريقة للقيام بذلك هي مع استخدام كتلة لأنه ينفذ تلقائيا .Dispose() في النهاية:

StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
    //do some stuff
}

وإذا قمت بإنشاء فئة باستخدام الكائنات غير المدارة, إذا كنت لا تنفذ IDisposable بشكل صحيح ، يمكن أن يسبب تسرب الذاكرة الخاصة بك فئة المستخدمين.

كل تسرب الذاكرة يتم حلها بواسطة برنامج إنهاء الخدمة.

تسرب ذاكرة كافية ونظام التشغيل قد تقرر حل المشكلة نيابة عنك.

وسوف نتفق مع برنارد كما أن في .صافي ما mem تسرب سيكون.

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

في إدارتها حيث سوف أضع رقبتي على خط القول فإنه لا يذهب بعيدا بمجرد عملية قتل/إزالة.

التعليمات البرمجية غير المدارة الخاصة به الوحش إذا تسرب موجود في داخلها ، وسوف تتبع معيار mem.تسرب التعريف.

كما نضع في اعتبارنا أن .صافي اثنين من أكوام واحد يجري كائن كبير كومة.أعتقد الكائنات تقريبا 85k أو أكبر توضع على هذه الكومة.هذه الكومة مختلف مدى الحياة القواعد العادية كومة.

إذا كنت تقوم بإنشاء ذاكرة كبيرة الهياكل (القاموس أو القائمة) أنه سيكون من الحكمة أن تذهب بحث ما نفس القواعد.

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

كائنات COM يمكن أن تكون خادعة ثو.إذا كنت دائما استخدام IDispose نمط لتكون آمنة.لقد عبر تشغيل عدد قليل من إمكانية التشغيل المتداخل الجمعيات التي تنفذ IDispose.المفتاح هنا هو الاتصال Marshal.ReleaseCOMObject عندما كنت فعلت مع ذلك.كائنات COM لا تزال تستخدم معيار COM إشارة العد.

وجدت .صافي الذاكرة التعريف مساعدة جيدة جدا عند العثور على تسرب الذاكرة في .صافي.انها ليست مجانية مثل Microsoft CLR التعريف ، ولكن هو أسرع و أكثر لهذه النقطة في رأيي.A

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

للحصول على مزيد من المعلومات ، يرجى زيارة http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html.

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