متى يجب علي تعيين متغير إلى "لا شيء" في VB6؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

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

Private m_frm1 as MyForm
Private m_frm2 as MyForm

// Later...
Set m_frm1 = New MyForm
Set m_frm2 = New MyForm

لقد لاحظت أنني أقوم بتسريب الذاكرة عندما يتم إنشاء هذا النموذج (الأصل) وتدميره.هل من الضروري بالنسبة لي أن أقوم بتعيين متغيرات الأعضاء هذه لـ Nothing في Form_Unload()?

على العموم متى يكون ذلك مطلوبا؟

تم حلها:تم إصلاح تسرب الذاكرة هذا عندما قمت بذلك Unload على النماذج المعنية، وليس عندما أقوم بتعيين النموذج إلى Nothing.لقد تمكنت من إزالة بعض حالات تسرب الذاكرة الأخرى عن طريق تعيين بعض مثيلات Class Modules بشكل صريح على Nothing, ، أيضًا.

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

المحلول

@ Matt Dillard - هل أدى ضبط هذه العناصر إلى عدم إصلاح تسرب الذاكرة لديك؟

لا يحتوي VB6 على جامع قمامة رسمي، على غرار ما قاله @Konrad Rudolph.

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

لقد اختبرت هذا باستخدام مشروع فارغ ونموذجين فارغين.

Private Sub Form_Load()
  Dim frm As Form2
  Set frm = New Form2
  frm.Show
  Set frm = Nothing
End Sub

بعد تشغيل كلا النموذجين يتم تركهما مرئيين.الإعداد frm إلى لا شيء كان جيدًا ...لا شئ.

بعد ضبط frm على لا شيء، يكون المقبض الوحيد المفتوح لهذا النموذج هو عبر المرجع.

Unload Forms(1)

هل أرى المشكلة بشكل صحيح؟

  • جوش

نصائح أخرى

في الواقع، ينفذ VB6 رايي تمامًا مثل C++ مما يعني أنه يتم تعيين المراجع المعلنة محليًا تلقائيًا Nothing في نهاية الكتلة.وبالمثل، فإنه يجب إعادة تعيين متغيرات فئة الأعضاء تلقائيًا بعد التنفيذ Class_Terminate.ومع ذلك، كانت هناك العديد من التقارير التي تفيد بأن هذا لا يتم بشكل موثوق.لا أتذكر أي اختبار صارم ولكن من أفضل الممارسات دائمًا إعادة تعيين متغيرات الأعضاء يدويًا.

@ مارتن

يحتوي VB6 على عبارة "With/End With" التي تعمل "مثل" عبارة Use() في C#.NET.وبطبيعة الحال، كلما كانت الأشياء الأقل عالمية لديك، كلما كان ذلك أفضل بالنسبة لك.

مع/إنهاء بـ لا يعمل مثل عبارة الاستخدام، ولا يتم "التخلص" في نهاية العبارة.

يعمل With/End With في VB 6 تمامًا كما هو الحال في VB.Net، فهو في الأساس طريقة لاختصار استدعاء خصائص/طرق الكائن.على سبيل المثال

مع Acustomer .FirstName = "John" .lastname = "Smith" End with

الكائنات في VB لها حساب مرجعي.هذا يعني أن الكائن يحتفظ بعدد متغيرات الكائن الأخرى التي تحمل مرجعًا إليه.في حالة عدم وجود أي مراجع للكائن، يتم تجميع البيانات المهملة (في النهاية) للكائن.هذه العملية جزء من مواصفات COM.

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

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

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

بالمعنى الدقيق للكلمة أبدًا، لكنه يعطي لجامع القمامة تلميحًا قويًا لتنظيف الأمور.

كقاعدة: افعل ذلك في كل مرة تنتهي فيها من كائن قمت بإنشائه.

يؤدي تعيين مرجع VB6 إلى لا شيء إلى تقليل عدد المراجع التي يمتلكها VB لهذا الكائن.إذا كان العدد صفرًا فقط، فسيتم تدمير الكائن.

لا تعتقد أنه فقط لأنك قمت بالضبط على لا شيء، فسيتم "جمع البيانات المهملة" كما هو الحال في .NET

يستخدم VB6 عدادًا مرجعيًا.

ننصحك بضبط الكائنات التي تم مثيلها على "لا شيء" والتي تشير إلى كود C/C++ وأشياء من هذا القبيل.لقد مر وقت طويل منذ أن لمست VB6، لكني أتذكر ضبط الملفات والموارد على لا شيء.

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

يحتوي VB6 على عبارة "With/End With" التي تعمل "مثل" عبارة Use() في C#.NET.وبطبيعة الحال، كلما كانت الأشياء الأقل عالمية لديك، كلما كان ذلك أفضل بالنسبة لك.

تذكر أنه في كلتا الحالتين، أحيانًا يكون إنشاء كائن كبير أكثر تكلفة من الاحتفاظ بمرجع حيًا وإعادة استخدامه.

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

لقد قمت بسحب الكود القديم ويبدو كالتالي:

Dim y As Long
For y = 0 To Forms.Count -1
    Unload Forms(x)
Next

قد يكون من الآمن إلغاء تحميل ملف m_frm1.وليس فقط تعيينه على لا شيء.

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

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

لذلك من المهم أن تدرك أن تعيين مرجع كائن إلى لا شيء يمكن أن يؤدي إلى حدوث خطأ، والتعامل معه وفقًا لذلك (بالضبط كيف سيعتمد ذلك على التطبيق الخاص بك - على سبيل المثال، يمكنك تجاهل مثل هذه الأخطاء عن طريق إدراج "On Error Resume Next" قبل " تعيين ...= لا شيء").

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