سؤال

لدينا تطبيق C++ أصلي يعمل عبر COM+ على خادم Windows 2003.لقد لاحظت مؤخرًا من عارض الأحداث أنه يطرح استثناءات، وتحديدًا استثناء C0000005، والذي، وفقًا لـ http://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspx يعني أن العملية تحاول الكتابة إلى الذاكرة خارج مساحة العنوان الخاصة بها، والمعروف أيضًا باسم انتهاك الوصول.

يوفر الإدخال في عارض الأحداث مكدس استدعاءات:

libfmwk! util_getDateFromLogByDayDirectory (char const *، class utilcdate &) + 0xa26c libfmwk! util_getDateFromLogByDayday (char const *، class utilcdate &) + 0x8af4 libfmwk! x13a1 libfmwk! utilClogController :: getFlfinfolevel (void ) const + 0x1070 libfmwk! utilClogController :: getFlfinfolevel (void) const + 0x186

الآن، أفهم أنه يعطيني أسماء الطرق لألقي نظرة عليها ولكن لدي شعور بأن العنوان الموجود في نهاية كل سطر (على سبيل المثال:+ 0xa26c) يحاول توجيهي إلى سطر أو تعليمات معينة ضمن هذه الطريقة.

لذلك أسئلتي هي:

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

يحرر:كما هو مطلوب، إليك الطريقة التي يبدو أنها تسبب المشكلة:

BOOL UTIL_GetDateFromLogByDayDirectory(LPCSTR pszDir, utilCDate& oDate)
{
BOOL bRet = FALSE;

if ((pszDir[0] == '%') &&
    ::isdigit(pszDir[1]) && ::isdigit(pszDir[2]) &&
    ::isdigit(pszDir[3]) && ::isdigit(pszDir[4]) &&
    ::isdigit(pszDir[5]) && ::isdigit(pszDir[6]) &&
    ::isdigit(pszDir[7]) && ::isdigit(pszDir[8]) &&
    !pszDir[9])
{
    char acCopy[9];
    ::memcpy(acCopy, pszDir + 1, 8);
    acCopy[8] = '\0';

    int iDay = ::atoi(&acCopy[6]);
    acCopy[6] = '\0';
    int iMonth = ::atoi(&acCopy[4]);
    acCopy[4] = '\0';
    int iYear = ::atoi(&acCopy[0]);

    oDate.Set(iDay, iMonth, iYear);

    bRet = TRUE;
}

return (bRet);

}

هذا رمز تمت كتابته منذ أكثر من 10 سنوات بواسطة أحد أعضاء شركتنا الذي رحل منذ فترة طويلة، لذلك لا أفترض أنني أعرف بالضبط ما يفعله هذا ولكني أعرف أنه متورط في عملية إعادة تسمية دليل السجل من "اليوم" إلى التاريخ المحدد، على سبيل المثال.%20090329.إن فهرسة المصفوفة وmemcpy وعنوان المشغلين تجعل الأمر يبدو مريبًا إلى حد ما.

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

مقدر جدا!آندي

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

المحلول

إذا كنت تريد حقًا تعيين هذه العناوين لوظائفك - فستحتاج إلى العمل مع ملف .MAP ومعرفة المكان الذي تشير إليه هذه العناوين حقًا.

لكن كوني في وضعك أفضل التحقيق في هذه المشكلة ضمن مصحح الأخطاء (على سبيل المثال.مصحح أخطاء MSVS أو Windbg)؛كبديل (في حالة حدوث عطل في موقع العميل)، يمكنك إنشاء تفريغ الأعطال ودراسته محليًا - يمكن القيام بذلك عبر Windows MiniDumpWriteDump API أو الأداة المساعدة SysInternals ProcDump (http://download.sysinternals.com/Files/procdump.zip).

تأكد من إنشاء كافة ملفات الرموز المطلوبة وإتاحتها (وأيضًا قم بإعداد مسار خادم رموز Microsoft بحيث يتم حل نقاط إدخال ملفات DLL الخاصة بنظام التشغيل Windows أيضًا).

IMHO هذا هو موقع الويب الذي تحتاجه فقط: http://www.dumpanaتحليل.org - وهو أفضل مورد لتغطية جميع أسئلتك.فكر أيضًا في إلقاء نظرة على ملف PDF هذا - http://windbg.info/download/doc/pdf/WinDbg_A_to_Z_color.pdf

نصائح أخرى

وقد قال آخرون هذا بين السطور، ولكن ليس صراحة.ينظر الى:

LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c

الإزاحة 0xa26c هي ضخم, ، بعد نهاية الوظيفة.من الواضح أن مصحح الأخطاء لا يحتوي على الرموز المناسبة لـ LibFmwk، لذا فهو يعتمد بدلاً من ذلك على صادرات DLL ويعرض الإزاحة بالنسبة لأقرب رمز يمكنه العثور عليه.

لذا، نعم، احصل على الرموز المناسبة ومن ثم يجب أن يكون الأمر سهلاً.UTIL_GetDateFromLogByDayDirectory ليس مخطئًا هنا.

يتم الرد بسهولة على النقطة 2 و 3:

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

النقطة الثانية.أي معلومات حول مجمع x86 والهندسة العكسية ...يحاول: أوبن آر سي إي, وثائق NASM, مجتمع ASM.

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

إذا كان بإمكانك معرفة المزيد عن البرنامج (ما هي أجزاء الكود المصدري لديك، هل يتم استدعاء المكتبة؟، ...)


الآن بعض قراءة التعليمات البرمجية:

تقبل الدالة مؤشرًا إلى سلسلة منتهية صفرية ومرجعًا إلى كائن تاريخ.من المفترض أن يكون المؤشر صالحًا!

تتحقق الوظيفة مما إذا كانت السلسلة بتنسيق معين (% متبوعة بـ 8 أرقام متبوعة بـ \0).إذا لم يكن هذا هو الحال، فإنه يعود كاذبة.يصل هذا الاختيار (علامة if الكبيرة) إلى المؤشر دون أي عمليات تحقق من الصلاحية.لم يتم تحديد الطول وإذا كان المؤشر يشير إلى مكان ما في البرية، فسيتم الوصول إلى هذه المساحة.لا أعرف ما إذا كانت السلسلة الأقصر ستسبب مشاكل.لا ينبغي ذلك بسبب الطريقة التي يتم بها تقييم &&.

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

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

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

أتمنى ألا أكون قد ارتكبت أي أخطاء كبيرة لأنني مبرمج دلفي.إذا فعلت ذلك - فلا تتردد في التعليق.

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