Russian Qt Forum
Ноябрь 25, 2024, 07:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Не понимаю в чём ошибка, так что и описать её  (Прочитано 10289 раз)
chron1c
Гость
« : Август 04, 2012, 22:42 »

Здравствуйте.
Столкнулся с одной проблемой, которую не в силах объяснить, поэтому и название темы не информативное.

Задача куска кода: пробежаться по всем позициям спутника за заданный интервал и посчитать в каких местах радиосигнала накапливается больше.

satList - это QList из QList'ов.
Каждый элемент satList'a - это QList, состоящий из:
Код:
struct eph {
QString date;
float latitude;
float longitude;
float zrvLat[37];
float zrvLon[37];
};

activeSats - это QList, в котором хранятся индексы элементов satList, выбранных для отображения.
( на форме просто чекбокс, в котором выбирается что отображать, а что - нет )
activeSatsNum - это activeSats.count();

ephIndex - это индекс структуры из элемента satList'a.
intervalBegin и intervalEnd - это с какого по какой индексы нужно отобразить структуры.

patterns - это QList, состоящий из структур вида:
Код:
struct pattern {
int cm; // col modofyer
bool m[180][360];
};

В этом листе лежат шаблоны.
Шаблон есть матрица 180 на 360, в которой true установлена для ячеек, соответствующих зоне, в которой сигнал от спутника есть.
Т.е. есть набор шаблонов, соответствующих широте от 0 до 90, и, в зависимости от текущей широты, для которой происходят вычисления, выбирается тот или иной шаблон.
Поскольку форма зоны радиовидимости для широт от 0 до 90 и от 0 до -90 - зеркальная, то при отрицательной широте флаг inverted устанавливается в true;

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

Соответственно, patternIndex - это индекс шаблона для конкретной широты.


Код:
	int indx, satIndex, ephIndex, patternIndex, cm, currentCol, row, i, j;
        bool inverted;
        float latitude;

for( indx = 0, satIndex = activeSats.at(indx); indx < activeSatsNum; indx++)
{
for( ephIndex = intervalBegin; ephIndex <= intervalEnd; ephIndex++)
{
inverted = false;
latitude = satList->at(satIndex)->at(ephIndex).latitude;

if(latitude < 0)
{
inverted = true;
latitude *= -1;
}

                        // т.е. patternIndex - int, а latitude - float, то так я грубо получаю индекс шаблона для соответствующей широты.
patternIndex = latitude; // ! вот здесь начинается интересное, подробности ниже.

if(patternIndex >= 83) continue; // "затычка" на случай если индекс уйдёт за границы patterns.

cm = patterns->at(patternIndex).cm;
currentCol = (satList->at(satIndex)->at(ephIndex).longitude + 180); // т.к. долгота - это диапазон из значений от -180 до +180, а моя матрица - от 0 до 360.

for(i = 0; i < 180; i++)
for(j = 0; j < 360; j++)
if(patterns->at(patternIndex).m[i][j])
{
row = i;  // это если рассчёт идёт для отрицательной широты
if(inverted) row = 180 - row;
rm->slotAddToMatrix(row, currentCol + (j - cm));
}
else ;

QApplication::processEvents(0);
ui.debug->append(QString::number(indx+1) + "/" + QString::number(activeSatsNum) + "::" + QString::number(ephIndex) + "/" + QString::number(intervalEnd));
}

}

rm->addToMatrix(int row, int col) добавляет в ячейку(row)(col) результирующей матрицы еденицу, отмечая этим что в данном кванте поверхности радиосигнал присутствовал.
Если представить циллиндрическое изображения Земли, то на него как бы наложена матрица, каждая ячейка которой представляет собой квант поверхности 1° на 1°.
( не совсем так, конечно, т.к. в приполярный зонах 1° - это совсем не один квадрат, а вся линия. )
Также в rm есть проверка на границы переданных значений и, если столбец превышает 359 или меньше 0, то "перебрасывает" его через нулевой меридиан.

Так вот, в чём вся штука, если в месте, которое я отметил, написать:
Код:
patternIndex = <любое int значение>; //не выходящее за границы patterns, конечно
, то всё работает, иначе - вываливается с ошибкой.
Причем не в конкретно этом месте, а на следующей интерации цикла.

Переменные объявлены вне циклов т.к. это я уже плясками с бубном занимался.
Не уверен, стоило ли использовать QList для таких целей, но как-то он мне понравился.
Раньше всё работало, а стоило мне поменять размерность матриц с [360][720] на [180][360] - началось такое.
Сами шаблоны составлены корректно, проверял как они отображаются по одному.

Не знаю даже в чём проблема.
Если нужно - приведу скрин ошибки.
Возможно, объяснил не очень, если возникнут вопросы - задавайте.
« Последнее редактирование: Август 04, 2012, 22:46 от chron1c » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Август 04, 2012, 23:34 »

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

- убрать все "числа", использовать как положено константы (на худой конец #define) т.е. напр  m[180][360] заменить на m[LAT_DIV][LONG_DIV]. Конечно это всем известно, но частенько думается "та ладно, и так работает"

- окружить вычисление индексов ассертами, напр

Код
C++ (Qt)
assert(i >= 0 && i < LAT_DIV);
assert(j >= 0 && j < LONG_DIV);
int val = m[i][j];
 
Ну в общем, писать культурно  Улыбающийся
Записан
chron1c
Гость
« Ответ #2 : Август 05, 2012, 00:52 »

Да, прекрасно понимаю, да и с точки зрения просто логики всё впоряде здесь.
Мне и казалось изначально, что дело в каких-то тонкостях, которых я просто не знаю по неопытности.

Сделал как вы сказали, размерность матрицы для шаблона через константы задал, циклы тоже до констант бегать пустил.
Два раза всё отработало нормально, потом всё снова начало падать, только с разными ошибками.

Первый раз слышу, что предпочтительнее использовать контанты в таких случаях. Чем числа плохи?
Про assert не совсем понял, какое именно место вы имеете ввиду?

И можно ли где-нибудь почитать о подобных вещах? Хочу научиться писать культурно. Собственно, первая моя серьёзная программа.

Лично меня смущает, что приходится использовать столько QList'ов, столько много получается обращений к разным их элементам.
И почему-то кажется, что лучше использовать не структуру, а класс, и все внутренние переменные сделать private, а для доступа к ним написать соответствующие методы.

Как посоветуете поступить?
Спасибо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Август 05, 2012, 06:25 »

Не цитирую чтобы не раздувать пост, здесь и так понятно на что ответы

Числа плохи тем что по мере разрастания кода их потом хрен найдешь, возможно Вы и стали жертвой. По поводу private - удобный случай изучить принципы ООП на деле. Только не лепить тупо get/set, а конкретно. Напр у Вас есть такое m[ i ][ j ].  Это никак не контролируется, если произошла запись за границы - память испорчена и падения могут быть где угодно. Вот и сделайте m private, а в методах get/set воткните assert

« Последнее редактирование: Август 05, 2012, 11:17 от Igors » Записан
DmitryM
Гость
« Ответ #4 : Август 05, 2012, 10:41 »

Используй std::vector и метод at. При выходе за грани массива, at кидает исключение.
Вычисления точно должны происходить в геодезических координатах, а не в госк'е?
Записан
chron1c
Гость
« Ответ #5 : Август 05, 2012, 14:56 »

Igors, перед тем, как смотреть true или false значение в матрице, у меня стоит assert() на и i и j, так что дело там вряд ли в выходе за границы, но всё равно попробую таки сделать, "для четкости".

DmitryM, так QList - почти тот же вектор, не?
По поводу координат - да.
Записан
chron1c
Гость
« Ответ #6 : Август 05, 2012, 18:41 »

Так.
Попробовал использовать QVector вместо QList для хранения элементов.
Прочитал в документации, что если вес элемента больше указателя или стандартных типов, то лучше использовать QVector.
Не помогло.

Решил каждый элемент списка создавать через new и в списка хранить указатели на элементы.
Тоже не помогло.

Заметил, что дело не только в обращении к файлу шаблона по индексу, но и то же самое происходит при попытке "дёрнуть" подспутниковую точку по индексу.

Дело не в выходе за границы списков и.т.п., проверял они в таком случае выкидывают ошибку, похожую на assert'овскую.

Скрины ошибок во вложении.

Заметил, что если загружать не больше 20 подспутниковых точек, то всё работает.
И ещё, кусок кода сначала нормально отрабатывает, показывается результат, а потом выкидывает ошибку номер 2. ( ели успел заметить, что отработала графика )
1-ая же ошибка получается когда объём данных увеличивается.

Перепробовал, как мне кажется, всё, куда копать - ума не приложу.

Ах, и да, кусок кода где не идёт поиндексное обращение в цикле к подспутниковым точкам, работает нормально.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #7 : Август 05, 2012, 19:47 »

надо смотреть свои методы в стеке вызовов (если они там конечно есть), а не библиотечные. думаю происходит обращение к удалённому элементу.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
chron1c
Гость
« Ответ #8 : Август 05, 2012, 19:58 »

Но в ходе выполнения программы ничего не удаляется.
Поэтому-то я и в замешательстве.
Вроде ведь даже для каждого элемента отвёл своё место в куче.
Думал сначала, что, может, какие-то проблемы с распределением памяти.
Записан
DmitryM
Гость
« Ответ #9 : Август 05, 2012, 20:59 »

DmitryM, так QList - почти тот же вектор, не?
По поводу координат - да.
Сори, возможно лучше заменить обычные массивы в  eph, pattern.
Стандартные контейнеры бросают исключения, а Qt'шные нет.
По поводу координат, наверное спутники по углу возвышения в другом месте отбрасываются.
« Последнее редактирование: Август 05, 2012, 21:37 от DmitryM » Записан
chron1c
Гость
« Ответ #10 : Август 06, 2012, 10:06 »

Заменить обычные массивы? Но на что?
В плане выхода за границы Qt'шные тоже бросают.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Август 06, 2012, 13:16 »

Перепробовал, как мне кажется, всё, куда копать - ума не приложу.
Попробуйте "вцепиться" в ошибку, такая возможность есть. Ну вот напр 2.png - явно виджет испорчен, возможно повторное удаление. Добавляете отладочную печать в деструкторе
Код
C++ (Qt)
MyWidget::~MyWidget( void )
{
qDebug() << "destructor" << this;
}
 
А так менять здесь и там "а вдруг поможет" можно долго но безуспешно
Записан
chron1c
Гость
« Ответ #12 : Август 06, 2012, 17:44 »

Проверил, деструктор не вызывается. ( Хотя какой виджет проверять? )
Проверял тот, в который значения добавляются, ну и главный.

Есть ещё класс, код которого абсолютно такой же как и тот, который я пытаюсь использовать при ошибке.
Если подставить элемент класса-копии, то всё работает.
Т.е. написать в цикле, например, не
Код:
rm->slotAddToMatrix();
, а
Код:
clm->slotAddToMatrix();
, то всё работает.

Т.е. если проблема в классе, то непонятно в чём именно, т.к. код в точности идентичный.

Создаются элементы этих двух классов одинаково, обрабатывается всё в разных слотах одинаково.

Класс-копию я создал скопировав код "проблемного" класса и поменяв имена. ( Он для других целей используется, но похжих. )
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Август 06, 2012, 19:22 »

Выкладывайте минимальный сбойный проект, а то прогресса нет
Записан
DmitryM
Гость
« Ответ #14 : Август 06, 2012, 22:04 »

Попробуй запустить cppcheck, статические анализаторы могут дать что-нибудь, для размышления.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.095 секунд. Запросов: 23.