Нарушение доступа VC ++ 6.0 при запуске в отладчике - PullRequest
1 голос
/ 17 декабря 2008

Я пытаюсь добавить улучшения в 4-летнюю программу VC ++ 6.0. Сборка отладки запускается из командной строки, но не в отладчике: происходит сбой с нарушением доступа внутри 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

С уважением,

--- Алистер.

Ответы [ 6 ]

3 голосов
/ 17 декабря 2008

Вы можете использовать _CrtSetDbgFlag(), чтобы включить кучу полезных методов отладки кучи. Существует множество других функций отладки CRT , которые должны помочь вам отследить, где ваша проблема.

3 голосов
/ 17 декабря 2008

При запуске из отладчика используется другая куча; это называется куча отладки . Это поведение отличается от кучи, используемой вне отладчика, и призвано помочь вам обнаружить проблемы, подобные этой.

Обратите внимание, что Win32 "куча отладки" отличается от VC ++ "куча отладки"; однако оба предназначены для более или менее одинакового действия. См. эту статью , которая описывает разницу в поведении при запуске приложения в отладчике.

В этом случае вы, вероятно, повредили кучу перед вызовом этой функции, либо записав конец, либо выключив начало блока кучи.

2 голосов
/ 17 декабря 2008

Самый простой из подходов (при условии, что ваше приложение не использует слишком много памяти) - это включить проверку кучи полной страницы (которая будет помещать так называемую защитную страницу после страницы памяти, с которой вы выделены, что, в свою очередь, точно указать место в вашем коде, где происходит коррупция).

Учитывая, что у вас есть средства отладки Windows , запустите следующую команду gflags, чтобы сконфигурировать кучу полной страницы:

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

Обратите внимание, вы должны указать только имя исполняемого файла (т.е. без префикса пути!)
Затем просто запустите его под отладчиком - он сломается с первой попыткой испортить кучу. Разница здесь в том, что повреждения кучи - это в основном отложенные дефекты, которые проявляются позже, когда (возможно) действительная операция кучи действует.

Примечание, также:

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

дополнительно разместит защитную страницу до вашего размещения.

При запуске с параметром / p будут отображаться параметры страницы кучи, действующие в данный момент.

1 голос
/ 17 декабря 2008

Я подозреваю, что jmattias прав. Основная причина проблемы, скорее всего, где-то еще, чем там, где происходит сбой.

Многое может вызвать повреждение кучи.

  • запись за концом (или началом) выделенного блока памяти.
  • освобождение указателя дважды или освобождение указателя, который не был выделен.
  • многопоточность вашей программы и связывание с однопоточным (не многопоточным) RTL.
  • выделение памяти из одной кучи и освобождение ее из другой кучи.
  • и т. Д., И т. Д.,

Поскольку вы используете Visual C ++, вы можете использовать функцию _CrtSetDbgFlag () кучи отладки, чтобы включить проверку ошибок. Вы можете установить его для проверки целостности кучи при каждом вызове malloc или free. Это будет работать очень медленно, но оно должно точно определить, где ошибка для вас.

Поиск _CrtSetDbgFlag в документации по компилятору.

1 голос
/ 17 декабря 2008

У вас может быть ошибка повреждения кучи. Возможно, ваше приложение повредило кучу до вызова open_new_log().

0 голосов
/ 17 декабря 2008

У меня есть подозрение, что есть DLL, скомпилированная с другой версией среды выполнения C ++, чем остальная часть приложения. Это часто приводит к нарушениям «память по адресу XXX не может быть прочитана / записана».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...