انتهاك الوصول إلى VC++ 6.0 عند تشغيله في مصحح الأخطاء

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

سؤال

أحاول إضافة تحسينات إلى برنامج VC++ 6.0 عمره 4 سنوات.يتم تشغيل بناء تصحيح الأخطاء من سطر الأوامر ولكن ليس في مصحح الأخطاء:يتعطل بسبب انتهاك الوصول داخل printf().إذا قمت بتخطي printf، فسوف يتعطل في malloc() (يتم استدعاؤه من داخل fopen()) ولا يمكنني تخطي ذلك.

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

هل لديك أي فكرة عن سبب فشل printf() و malloc() عند التشغيل ضمن مصحح أخطاء VC++؟أنا لست جيدًا في هذه الأشياء ذات المستوى المنخفض!

إليك مكدس الاستدعاءات بعد انتهاك الوصول:

_heap_alloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 24, int 0, int 2, const char * 0x0046b3d8 `string', int 225) line 242 + 21 bytes
_malloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 163 + 27 bytes
_lock(int 2) line 225 + 19 bytes
_getstream() line 55 + 7 bytes
_fsopen(const char * 0x00468000 `string', const char * 0x00466280 `string', int 64) line 61 + 5 bytes
fopen(const char * 0x00468000 `string', const char * 0x00466280 `string') line 104 + 15 bytes
open_new_log(const char * 0x00468000 `string') line 66 + 14 bytes
log_open(const char * 0x00468000 `string', int 0) line 106 + 9 bytes
Xlog_open(const char * 0x00468000 `string', int 0) line 51 + 13 bytes
service_start(unsigned long 1, char * * 0x009a0e50) line 3152 + 12 bytes
service_init2(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, char * 0x00466540 `string', unsigned long 1, char * * 0x009a0e50) line 508 + 13 bytes
service_init(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, unsigned long 2, char * * 0x009a0e50) line 548
main(unsigned long 2, char * * 0x009a0e50) line 3131
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()

فيما يلي تفكيك التصحيح حتى العملية التي فشلت:

0041EA7E   jmp         _heap_alloc_dbg+2B3h (0041eb23)
0041EA83   mov         edx,dword ptr [_lTotalAlloc (004b4294)]
0041EA89   add         edx,dword ptr [nSize]
0041EA8C   mov         dword ptr [_lTotalAlloc (004b4294)],edx
0041EA92   mov         eax,[_lCurAlloc (004b429c)]
0041EA97   add         eax,dword ptr [nSize]
0041EA9A   mov         [_lCurAlloc (004b429c)],eax
0041EA9F   mov         ecx,dword ptr [_lCurAlloc (004b429c)]
0041EAA5   cmp         ecx,dword ptr [_lMaxAlloc (004b42a0)]
0041EAAB   jbe         _heap_alloc_dbg+249h (0041eab9)
0041EAAD   mov         edx,dword ptr [_lCurAlloc (004b429c)]
0041EAB3   mov         dword ptr [_lMaxAlloc (004b42a0)],edx
0041EAB9   cmp         dword ptr [_pFirstBlock (004b4298)],0
0041EAC0   je          _heap_alloc_dbg+25Fh (0041eacf)
0041EAC2   mov         eax,[_pFirstBlock (004b4298)]
0041EAC7   mov         ecx,dword ptr [pHead]
0041EACA   mov         dword ptr [eax+4],ecx

هنا هو المصدر الذي يستدعي fopen() ويفشل في malloc()

FILE *open_new_log( const char *logfile )
{
    FILE *fp;
    int retry = 0;

    while( ( fp = fopen( logfile, "w" ) ) == NULL && ++retry < 300 )
        Sleep( 1000 );

    return( fp );
}

الخطأ الذي أحصل عليه هو

Unhandled exception inPISCOOP.exe: 0xC00000005: Access Violation

يعتبر،

--- أليستير.

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

المحلول

ويمكنك استخدام _CrtSetDbgFlag() لتمكين مجموعة من التقنيات كومة التصحيح مفيدة. هناك مجموعة من ظائف التصحيح CRT المتاحة من شأنها أن تساعد على تعقب حيث مشكلتك هي.

نصائح أخرى

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

لاحظ أن Win32 و"كومة التصحيح" متميزة من VC ++ "كومة التصحيح". وتهدف على حد سواء لبذل المزيد من الجهد أو أقل نفس الشيء، ولكن. انظر هذه المقالة الذي يصف الفرق في السلوك عند تشغيل التطبيق تحت المصحح.

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

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

بالنظر إلى أن لديك أدوات تصحيح أخطاء Windows في متناول يديك، قم بتشغيل الأمر gflags التالي لتكوين كومة الصفحة الكاملة:

gflags[.exe] /p /enable yourapp.exe /full

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

لاحظ ايضا:

gflags[.exe] /p /enable yourapp.exe /full /backwards

بالإضافة إلى ذلك، سيتم وضع صفحة حماية قبل التخصيص الخاص بك.

سيؤدي التشغيل باستخدام رمز التبديل /p وحده إلى عرض خيارات صفحة الكومة سارية المفعول حاليًا.

قد يكون لديك علة الفساد الكومة. قد يكون طلبك تلف كومة قبل أن يتم استدعاء open_new_log().

أظن أن جماتياس على حق.من المحتمل أن يكون السبب الجذري للمشكلة في مكان آخر غير مكان التعطل.

هناك الكثير من الأشياء التي يمكن أن تسبب تلف الكومة.

  • الكتابة بعد نهاية (أو بداية) كتلة الذاكرة التي تم تخصيصها.
  • تحرير مؤشر مرتين، أو تحرير مؤشر لم يتم تخصيصه.
  • تعدد مؤشرات الترابط لبرنامجك والربط مع RTL أحادي الترابط (غير آمن).
  • تخصيص الذاكرة من كومة واحدة وتحريرها على كومة أخرى.
  • الخ، الخ،

نظرًا لأنك تستخدم Visual C++، يمكنك استخدام ميزة _CrtSetDbgFlag() الخاصة بكومة التصحيح لتشغيل التحقق من الأخطاء.يمكنك ضبطه للتحقق من سلامة الكومة عند كل مكالمة إلى malloc أو مجانًا.سيتم تشغيل ذلك ببطء شديد، ولكن يجب أن يحدد لك مكان الخطأ.

ابحث عن _CrtSetDbgFlag في مستندات المترجم.

ولدي شكوك بأن هناك DLL مترجمة مع إصدار مختلف من وقت التشغيل C ++ من بقية التطبيق. وهذا غالبا ما يؤدي إلى "الذاكرة في عنوان XXX تعذر 'قراءة' / 'كتب'" الانتهاكات.

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