Нарушение прав доступа VC++ 6.0 при запуске в отладчике

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

Вопрос

Я пытаюсь добавить улучшения в программу 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

С уважением,

--- Алистер.

Это было полезно?

Решение

Вы можете использовать _CrtSetDbgFlag() чтобы включить множество полезных методов отладки кучи.Есть масса других Функции отладки ЭЛТ доступный, который должен помочь вам отследить, в чем заключается ваша проблема.

Другие советы

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

Обратите внимание, что «куча отладки» 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 или free.Это будет работать очень медленно, но поможет вам определить, где находится ошибка.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top