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

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

С уважением,

--- Алистер.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
4 844
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

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

Использование отладочной кучи по сравнению с кучей relase определяется типом библиотеки времени выполнения C, с которой связано приложение, а не тем фактом, что код запускается в отладчике, т.е. запуск отладочной сборки приложения из командной строки будет используйте отладочную кучу.

jmatthias 17.12.2008 18:10

AFAIK, вы можете переключаться между отладочной кучей и не-отладочной кучей с помощью API, поэтому вполне может быть, что отладчик вызывает API, чтобы переключить его на версию с отладкой. Кроме этого - да, вы, вероятно, где-то испортили кучу.

Grey Panther 17.12.2008 18:14

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

Ответ принят как подходящий

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

Большое спасибо за все эти ответы. Я постараюсь взглянуть на это позже. Я думаю, что я решил проблему, из-за которой мне захотелось запустить ее в отладчике, поэтому приоритетность этого снизилась. Хотя я, очевидно, обеспокоен тем, что в коде выпуска может происходить скрытое повреждение.

user41013 18.12.2008 13:21

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

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

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

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

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

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

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

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

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

Также обратите внимание:

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

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

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

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

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