Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Ошибка Access violation. Что делать?


Автор: Avenger2k 23.5.2006, 23:17
При выполнении программы в этом участке кода:

Код

if (mField[dx][dy].Occupied == mColor) 
{
    mCollapse[count].x = dx;
    mCollapse[count].y = dy;
    count++;
}


вылетает такая ошибка
Unhandled exception at 0x0040622e in Demo4_debug.exe: 0xC0000005: Access violation reading location 0x000052b7.

Вылетает именно на строчке 
Код

if (mField[dx][dy].Occupied == mColor) 


т.е. что-то не так с массивом.

НО, такие же инструкции есть практически во всем коде и везде все работает нормально. Все процедуры и функции отрабатывают на ура, но вот стоило добавить еще одну функцию, работающую с этим массивом и на тебе  smile 

вот пример других циклов, которые никаких ошибок не вызывают:

Код

    for (int i=0;i<MapWidth; i += 2)
    {
        for (int j=0; j<MapHeight; j++)
        {

            if (mField[i][j].Occupied != NOTHING_IN)
            g->DrawImageCel....


В дебаге сижу уже вторые сутки и ничего не могу добиться. Мочему-то массив получается не инициализированным именно в этой функции, хотя перед ее вызовом идет явная инициализация всех данных массива, его полное заполнене и еще вызывается несколько функций, которые с этим массивом работают!  smile 

Кто-нибудь сталкивался с такими чудесами или может есть дельные мысли? Коллеги, нужна Ваша помощь!  smile  

Автор: DeadSoul 23.5.2006, 23:42
Скорее всего этот mField указатель указывает куда-то не туда  

Автор: Avenger2k 24.5.2006, 00:48
mField - это не указатель, а статический массив  smile  

Автор: Kostt 24.5.2006, 07:00
думаю dx, dy или count вылазят за границы массива, либо он не инициализирован во время вызова функции 

Автор: skyboy 24.5.2006, 08:29
А почему это сразу обращение "за пределы" должно происходить в той же строке, где происходит сбой? Кто-то до этого(может, намного раньше) тихонько потёр память и сказал : "это моё", а сбой произошёл только тогда, как твой статистический массив пришёл и начал качать права: "это моё место!".. Вот и возник Access violation. А бага почти наверняка - при работе с указателями либо использовались неинициализированные указатели, не равные nil, либо был выход за пределы массива в динамическом массив(уж не знаю, как эта штука выглядит в С++).. 

Автор: Earnest 24.5.2006, 09:27
Нет, 
Код

0xC0000005: Access violation reading location 0x000052b
явно указывает на то, что вычисленный адрес попал на запрещенную область, и именно в этой строке. Проверь отладчиком свои dx, dy - это явный выход за границы. Посмотри адрес начала массива и прикинь, где находится этот 0x000052b. Кстати, уже видно, что это запрещенная область, без всякого отладчика. Возможно, в результате сбоя твои dx, dy отрицательными стали? 

Автор: Avenger2k 24.5.2006, 13:21
Обращение "за пределы" происходит именно в этой строке. В отладчике если проверять работу кода по строчкам, то при переходе отладчика на эту строку и попытке ее выполнить прога вылетает.

dx, dy не вылезают за пределы.
Вот кусок кода чуть повыше проблемной строки:
Код

for (i = 1; i < 5; i++)
{
    if (i > 2) j = 2;
    if ((x - i >= 0) && (y - j >= 0))
    {
        dx = x - i;
        dy = y - j;
        if (mField[dx][dy].Occupied == mColor) 
        {


раньше dx, dy вообще не было, но я уже не знаю как изъ@%нуться, чтобы все заработало. Раньше было так: if (mField[x - i][y - j].Occupied == mColor)

Таким образом у нас dx, dy всегда больше или равно нулю. В других циклах, если к "x" и "y" прибавляется значение таким же образом проверяется, чтобы dx, dy были меньше размерности массива.

"x", "y" задаются как параметры для функции. Я для отладки спецом выбрал их значения в середине массива, чтобы любые неучтенные вычисления не вышли за пределы, но ошибка все равно вылетает.

Вечером сегодня посмотрю где находится 0x000052b. Самое ужасное, что меня выводит больше всего из рабочего состояния - это то, что таких проверок по всему коду разбросано как будто колхозник прошел и как пшеницу их сеял (т.е. ОЧЕНЬ много) и везде все работает окромя этой злосчастной функции  smile  

Автор: skyboy 24.5.2006, 14:37
У меня указатель Ptr: Pointer; В нём хранятся данные. В смысле, там указатель на реальные данные, а не на мусор. Перед ним объявлена строка Str:strin[6]. В строке 6 символов. Я записываю седьмой: Str[7]='F'. Он затирает старое значение указателя. Вопрос такой: когда у меня произойдёт сбой? Разве по факту записи в "не свою" ячейку? Или может, всё-таки, тогда,когда я попытаюсь работать с Ptr как с ссылкой на Tbutton? А если сбой произойдёт только при обращении, значит ли это, что ошибка у меня в обращении к объекту или, может, мне бы поискать ту самую строку Str[7]:='F', которая находится на 2 страницы ранее по листингу?  

Автор: Earnest 24.5.2006, 16:06
Да, верно, если dx, dy правильные, проверь значение указателя mField. И не говори, что это не указатель. Адрес-то все равно есть. Странно, конечно, если mField - статическая переменная, но чего только не бывает...

Попробуй сделать полный ребилд всего приложения. Иногда бывают глюки с не-отслеживанием зависимостей. 

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

Добавлено @ 16:07 
Кстати, проверь еще, может это mColor испорчен, а не mField... 

Автор: Avenger2k 24.5.2006, 16:13
 smile  Вроде бы нашел в чем причина, но суть ее не понимаю. 

Перед тем, как производить какие-то действия с массивом в этой функции я считываю одно значение массива и записываю ее в переменную
Код

mColor = mField[x][y].Occupied;


затем я объявляю еще один одномерный массив (локальный) и в цикле заполняю его данными
Код

for (i=0;i<18;i++) 
{
    mCollapse[i].x = -1;
    mCollapse[i].y = -1;
}


Так вот перед тем, как заполнить новый массив  mField указывает на один адрес памяти, а после заполнения mCollapse - уже на другой. В следствии чего возникает ошибка.

Может кто-нибудь объяснить как заполнение одного локального массива данными может повлиять на то, куда указывает указатель на другой массив объявленный как глобальная переменная? Чет это у меня в голове не укладывается  smile 

Спасибо всем, кто откликнулся на мою просьбу о помощи. Выяснив причину теперь надо понять как такое могло произойти  smile 

P.S. skyboy, это ты к чему?  

Автор: skyboy 24.5.2006, 16:18
в приведённом тобою коде все нормально с индексами? там точно 18 элементов - в массиве mCollapse? 

Автор: Avenger2k 24.5.2006, 19:00
Цитата(skyboy @ 24.5.2006,  16:18)
в приведённом тобою коде все нормально с индексами? там точно 18 элементов - в массиве mCollapse?

...
Collapse mCollapse[17];
...


Код

struct Collapse
{
    int x;
    int y;
};
 

Автор: skyboy 24.5.2006, 20:06
Ты объявил массив из 17 элементов?А пытаешься обработать 18? Я тебя правильно понял?  smile  

Автор: Avenger2k 24.5.2006, 21:59
В С/С++ все начинается с нуля, т.е. объявляя 17 элементов у нас получится 0,1,2,3...17, итого 18
обрабатывается for (i=0;i<18;i++)  - от 0 до 17 

Автор: skyboy 24.5.2006, 22:11
Avenger2k, с нуля начинается адресация при доступе. Ты же объявил массив на 17 элементов, а пытаешься получить доступ к 18... Ведь если Collapse mCollapse[17]; - это 18 элементов, тогда Collapse mCollapse[0]; - это 1 элемент резервируется?! А как тогда объявить массив из 0 элементов? Collapse mCollapse[-1]?! Как это? 

Автор: Avenger2k 24.5.2006, 22:34
skyboy, хмм, кажись ты прав. Это у меня уже крышу срывает. По QuikWatch в дебаге глянул - заканчивается массив на mCollapse[16]. 
Главное прога все это дело проглатывает без малейшего возмущения. Временно объявил этот массив глобально и так же с ним работал (for (i=0;i<18;i++) ) и никаких ошибок это не вызывало нигде, даже в описанной выше функции.

Это баг или фича? (С) неизвестный издатель
 smile  

Всем спасибо, во всем разобрался.  smile  

Автор: skyboy 24.5.2006, 22:49
Avenger2k, это фича. Раз работа с указателями(чем и является работа с массивами) - то работа с указателями. Без никаких ограничений на использование индекса - вдруг ты хочешь получить доступ "не к своим" данным, но в виде массива? 

Автор: Avenger2k 25.5.2006, 19:06
Thx  smile  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)