غير صالحة مؤشر العملية في TMonitor.تدمير
-
20-09-2019 - |
سؤال
أنا أعمل حاليا على ترقية القائمة دلفي 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 في دلفي:
- النظام.TMonitor;وهو رقم قياسي, و يستخدم في موضوع التزامن.
- أشكال.TMonitor;وهي فئة تمثل المرفقة رصد (جهاز العرض).
النظام.TMonitor إضافة إلى دلفي منذ دلفي عام 2009 ؛ حتى إذا كنت ترقية رمز من دلفي 5 ما كان رمز باستخدام كانت الأشكال.TMonitor وليس النظام.TMonitor.
أعتقد أن اسم الفئة المشار إليها دون اسم الوحدة في التعليمات البرمجية الخاصة بك ، وهذا جعل الارتباك.