سؤال

أنا أعمل حاليا على ترقية القائمة دلفي 5 تطبيق دلفي 2010.

انها مؤشرات DLL (حيث المواضيع ولدت قبل Outlook) الذي يحمل في Outlook.عندما جمعت من خلال دلفي 2010, كلما أغمض شكل أركض إلى "مؤشر غير صالح العملية" داخل TMonitor.تدمير...واحد في النظام.با ، وهذا هو.

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

تحرير مكدس الاستدعاءات في لحظة حدوث المشكلة:

System.TMonitor.Destroy
System.TObject.Free
Forms.TCustomForm.CMRelease(???)
Controls.TControl.WndProc(???)
Controls.TWinControl.WndProc((45089, 0, 0, 0, 0, 0, 0, 0, 0, 0))
Forms.TCustomForm.WndProc(???)
Controls.TWinControl.MainWndProc(???)
Classes.StdWndProc(15992630,45089,0,0)
Forms.TApplication.ProcessMessage(???)
هل كانت مفيدة؟

المحلول

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

procedure TForm1.BeforeDestruction;
var
  MonitorPtr: PPMonitor;
begin
  MonitorPtr := PPMonitor(Integer(Self) + InstanceSize - hfFieldSize + hfMonitorOffset);
  Assert(MonitorPtr^ = nil);
  inherited;
end;

إذا كان هذا هو مشكلة في رمز الأصلي يجب أن تكون قادرة على الكشف عن ذلك في دلفي 5 إصدار DLL الخاص بك باستخدام FastMM4 إدارة الذاكرة مع جميع الشيكات تفعيلها.OTOH هذا يمكن أن يكون أيضا بسبب زيادة حجم البيانات الشخصية في بناء Unicode و في هذه الحالة سيكون واضح في DLL يبني باستخدام دلفي 2009 أو 2010.فإنه لا يزال فكرة جيدة لاستخدام أحدث FastMM4 مع جميع الشيكات.

تحرير:

من تتبع المكدس يبدو الشاشة تعيينه بالفعل.لمعرفة لماذا استخدام البيانات توقف.لم أكن قادرة على جعلها تعمل مع دلفي 2009 ، ولكن يمكنك أن تفعل ذلك بسهولة مع WinDbg.

في OnCreate معالج النموذج الخاص بك وضعت التالية:

var
  MonitorPtr: PPMonitor;
begin
  MonitorPtr := PPMonitor(Integer(Self) + InstanceSize - hfFieldSize + hfMonitorOffset);
  MessageDlg(Format('MonitorPtr: %p', [pointer(MonitorPtr)]), mtInformation,
    [mbOK], 0);
  DebugBreak;
  // ...

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

با م4 A32D00

استبدال A32D00 مع العنوان الصحيح من مربع الرسالة.مواصلة التنفيذ ، المصحح أن توقف عند رصد يحصل على تعيينه.باستخدام مختلف المصحح آراء (وحدات, المواضيع, كومة) قد تحصل على معلومات هامة عن الكود الذي يكتب هذا العنوان.

نصائح أخرى

مؤشر غير صالح العملية يعني البرنامج حاولت مجانا المؤشر ، ولكن كان هناك واحد من ثلاثة أشياء الخطأ في ذلك:

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

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

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

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

قلت المواضيع التي تم إنشاؤها من قبل Outlook.هل تعيين IsMultithread عالمي متغير ؟ البرنامج عادة مجموعات صحيح عندما يخلق الموضوع, ولكن إذا كنت لا إنشاء المواضيع ، فإنه سيبقى في الافتراضي قيمة كاذبة ، مما يؤثر على ما إذا كان مدير الذاكرة يكترث يحمي العالمية هياكل البيانات خلال تخصيص deallocation.تعيين إلى True في ملف DPR الرئيسية كتلة البرنامج.

بعد الكثير من البحث اتضح أنني كنت أقوم لطيفة (قراءة:مرعب ، ولكن تم بشكل صحيح تقوم بعملها في دلفي 5 تطبيقات الأعمار)

PClass(TForm)^ := TMyOwnClass 

في مكان ما في أعماق أحشاء لدينا تطبيق الإطار.على ما يبدو دلفي 2010 لديه بعض صف التهيئة لتهيئة "رصد الميدان" أن الآن لم يحدث, مما تسبب RTL محاولة "تحرير syncobject" على شكل الدمار بسبب getFieldAddress عاد غير معدومة القيمة.آآخ.

السبب لماذا كنا نفعل هذا الاختراق في المقام الأول لأنني أردت أن تتغير تلقائيا createParams على كل شكل من الحالات ، لتحقيق iconless يمكن تغيير حجم النموذج.لقد فتح سؤال جديد حول كيفية القيام بذلك دون rtl كسر الخارقة (و الآن سوف ببساطة إضافة لطيفة لامعة الرمز إلى أشكال).

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

هناك نوعان من TMonitor في دلفي:

  1. النظام.TMonitor;وهو رقم قياسي, و يستخدم في موضوع التزامن.
  2. أشكال.TMonitor;وهي فئة تمثل المرفقة رصد (جهاز العرض).

النظام.TMonitor إضافة إلى دلفي منذ دلفي عام 2009 ؛ حتى إذا كنت ترقية رمز من دلفي 5 ما كان رمز باستخدام كانت الأشكال.TMonitor وليس النظام.TMonitor.

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

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