LINUX.ORG.RU

где баг в коде?


0

1

Я не знаю где тут баг , но он есть . Причем иногда проявляется иногда нет

void COutlessPointer2Dlg::OnTimer( UINT_PTR nIDEvent)
{
	if( nIDEvent==TMR_RUNNING)
	{
		SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE);
		ZeroMemory( &gpsPos, sizeof( GPS_POSITION));
		if( m_CfgData.bGpsMode == 1)
		{
			//Test
			gps.GPSPortRead();
			CManualGPS::GPSMESSAGE m;
			ZeroMemory( &m, sizeof(CManualGPS::GPSMESSAGE));
			if( gps.GPSGetData( &m))
			{
				gpsPos.dblLatitude = m.fLattitude;
				gpsPos.dblLongitude = m.fLongitude;
				gpsPos.flAltitudeWRTSeaLevel = (float)m.fAltitude;
				gpsPos.dwSatelliteCount = m.dwSatellites;
				gpsPos.flHorizontalDilutionOfPrecision = m.fHDOP;
			}
#pragma region debug
			//debug
			/*CFile f;
			if( f.Open( L"\\GPS\\tmp.txt", CFile::modeWrite|CFile::modeCreate|CFile::modeNoTruncate))
			{
				CStringA sGpsCut("");
				sGpsCut.Format( "%d;%f;%f;%f;", m.dwSatellites, m.fLattitude, m.fLongitude, m.fAltitude);
				char ch[3] = {'\r','\n',0x00};
				sGpsCut += ch;
				COleDateTime dt( COleDateTime::GetCurrentTime());
				sGpsCut += dt.Format();
				sGpsCut += ch;
				f.SeekToEnd();
				f.Write( sGpsCut.GetBuffer(), sGpsCut.GetLength());
				f.Close();
			}*/
			//
#pragma endregion
		}
		else if( m_CfgData.bGpsMode == 0)
		{
			//GPS reading
			gpsPos.dwVersion = GPS_VERSION_1;
			gpsPos.dwSize = sizeof( GPS_POSITION);
			if( GPSGetPosition( hGPS, &gpsPos, 1000, 0)!=ERROR_SUCCESS)
			{
				ZeroMemory( &gpsPos, sizeof( GPS_POSITION));
			}
#pragma region debug
			//debug
			/*CFile f;
			if( f.Open( L"\\GPS\\tmp.txt", CFile::modeWrite|CFile::modeCreate|CFile::modeNoTruncate))
			{
				CStringA sGpsCut("");
				sGpsCut.Format( "%d;%f;%f;%f;", gpsPos.dwSatelliteCount, gpsPos.dblLatitude, 
					gpsPos.dblLongitude,  gpsPos.flHorizontalDilutionOfPrecision);
				char ch[3] = {'\r','\n',0x00};
				sGpsCut += ch;
				COleDateTime dt( COleDateTime::GetCurrentTime());
				sGpsCut += dt.Format();
				sGpsCut += ch;
				f.SeekToEnd();
				f.Write( sGpsCut.GetBuffer(), sGpsCut.GetLength());
				f.Flush();
				f.Close();
			}*/
			//
#pragma endregion
		}
		ZeroMemory( &gpsPosBest, sizeof( GPS_POSITION));
		DWORD dwTime = GetTickCount();
		m_GpsQueue[m_dwGpsQueueIndex].dwTime = dwTime;
		CopyMemory( &(m_GpsQueue[m_dwGpsQueueIndex].pos), &gpsPos, sizeof(GPS_POSITION));
		m_dwGpsQueueIndex++;
		if( m_dwGpsQueueIndex >= GPSQUEUESIZE) m_dwGpsQueueIndex = 0;
		
		DWORD dwMinHdopIndex = 0;
		for( int i = 1;i < GPSQUEUESIZE; i++)
		{
			DWORD dwPosTimeDelta = ( dwTime - m_GpsQueue[i].dwTime);
			if( dwPosTimeDelta <= 13000 && 
				m_GpsQueue[i].pos.flHorizontalDilutionOfPrecision >= 1.0f &&
				m_GpsQueue[i].pos.flHorizontalDilutionOfPrecision <= m_GpsQueue[dwMinHdopIndex].pos.flHorizontalDilutionOfPrecision &&
				m_GpsQueue[i].pos.dblLatitude!=0.0 && m_GpsQueue[i].pos.dblLongitude!=0.0)
			{
				if(m_GpsQueue[i].pos.flHorizontalDilutionOfPrecision < m_GpsQueue[dwMinHdopIndex].pos.flHorizontalDilutionOfPrecision)
					dwMinHdopIndex = i;
				else if(m_GpsQueue[i].dwTime > m_GpsQueue[dwMinHdopIndex].dwTime)
					dwMinHdopIndex = i;
			}
		}
		CopyMemory( &gpsPosBest, &(m_GpsQueue[dwMinHdopIndex].pos), sizeof(GPS_POSITION));
		
		if( gpsPosBest.flHorizontalDilutionOfPrecision >= 1.0f && gpsPosBest.flHorizontalDilutionOfPrecision < 6)
			m_btnLocate.EnableWindow( TRUE);
		else
			m_btnLocate.EnableWindow( FALSE);
		
		//Redraw
		m_nBlinkState = (m_nBlinkState==1)?0:1;
		Invalidate( FALSE);
	}
}

Извиняюсь за код под венду(mobile) , но смысл именно в баге в алгоритме кэширования показаний, а не в системе

Исправлять мне уже не нужно , но хочу понять ГДЕ? 4 часа по шагам разбирал .. так и не понял

Проблема в том , что иногда алгоритм начинает выдавать 0 значения, при нормальном сигнале с gps .. т.е. не отрабатывать как должно. отключаю кэширование и все работает ...

★★★★★

Последнее исправление: Loki13 (всего исправлений: 1)

Ответ на: комментарий от AoD314

Тут не такой баг .. у меня работает часами и все ОК , а у пользователей( у 1го из 100) просто пропадает сигнал

Loki13 ★★★★★
() автор топика
Ответ на: комментарий от Loki13

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

DELIRIUM ☆☆☆☆☆
()

valgring + вывод отладочной информации помогути Вам успешно конкурировать с ГЛОНАСС;-)))

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

AIv ★★★★★
()
Ответ на: комментарий от AIv

Там именно проблема в том , что при отключении этого мною придуманного кэширования все работает нормально. А глючит у 10 человек из 1000 . Просто подумал может кто умным незамыленным взглядом сразу увидит где я ошибку сделал

Loki13 ★★★★★
() автор топика
Ответ на: комментарий от Loki13

Там именно проблема в том , что при отключении этого мною придуманного кэширования все работает нормально.

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

и да, а если совсем отключить кеширование, что будет?

shty ★★★★★
()

Я бы чуть подправил

      DWORD dwTime = GetTickCount();
      m_GpsQueue[m_dwGpsQueueIndex].dwTime = dwTime;
      CopyMemory( &(m_GpsQueue[m_dwGpsQueueIndex].pos), &gpsPos, sizeof(GPS_POSITION));
      DWORD dwMinHdopIndex = m_dwGpsQueueIndex++;
      if( m_dwGpsQueueIndex >= GPSQUEUESIZE) m_dwGpsQueueIndex = 0;
      
      for( int i = 0; i < GPSQUEUESIZE; i++)
      {
          if (i == dwMinHdopIndex)
              continue;

И вот тут главный баг, с заворотом «двух суток»

          if(m_GpsQueue[i].dwTime > m_GpsQueue[dwMinHdopIndex].dwTime)

ly
()
Ответ на: комментарий от ly

Заворот «двух суток»? Я там проверяю , чтобы при одинаковой точности данные более свежие были

Loki13 ★★★★★
() автор топика
Ответ на: комментарий от nanoo_linux

А какая лицензия , если для внутренних нужд компании пишу , а не на продажу

Loki13 ★★★★★
() автор топика
Ответ на: комментарий от Loki13

Каждые двое суток TickCounter переполняется, поэтому на границе вместо «более свежие», будут «самые старые».

Нужно:

if ((int32_е)(m_GpsQueue[i].dwTime - m_GpsQueue[dwMinHdopIndex].dwTime) > 0) {
С dwPosTimeDelta аналогичная беда.

И еще, я бы не надеялся что данные от gps будут всегда правильными и корректными. Другими словами, нужно:

  • Если на итерации получить позицию не удалось, то в кеш ничего не помещать.
  • Убрать из цикла просмотра кэша все условаия кроме проверки точности и старости;
  • Точность и старость показаний пересчитать в линейный скалярный фактор, типа eligibility = 1.0 / (pos.dilution * sqrt(now - pos.timestamp));

Спорю «на пиво», что после этого заработает ;-)

ly
()
Ответ на: комментарий от ly

Точность и старость показаний пересчитать в линейный скалярный фактор, типа eligibility = 1.0 / (pos.dilution * sqrt(now - pos.timestamp));

Вот это идея интересная . А насчет некорректных данных и переполнения .. Корректность я выше проверяю , т.к. сам парсю данные с ком порта в умолчальном варианте , а в другом варианте майкрософт в апи своем проверяет . А переполнение тоже не важно , т.к. дольше одного дня подряд программа не запущена никогда .. рабочий день однако 8 часов всего . Хотя замечания верные конечно

Loki13 ★★★★★
() автор топика
Ответ на: комментарий от Loki13

Переполнение будет. Предположим пользователь запустил прогу через 47:59:59 после включения, т.е. примерно за секунду до часа Ч, когда dword с миллисекундами переполниться.

Тогда порядка TickCounter() «прокукарекает» 0xFFFFFF00,... 0xFFFFFFF0, ... 1, 10, 25...

Теперь подумай над if(m_GpsQueue[i].dwTime > m_GpsQueue[dwMinHdopIndex].dwTime)

ly
()
Ответ на: комментарий от ly

Неа не понял . Там смысл в том , что flHorizontalDilutionOfPrecision чем меньше - тем лучше , 1- максимальная точность , 50 - минимальная , а 0 - отсутствие сигнала. Выбирается , что если точность равна(других вариантов при таком построении условий нет) , то выбирать более свежий по времени

Loki13 ★★★★★
() автор топика
Ответ на: комментарий от Loki13

Нельзя сравнивать сами отметки времени. Нужно сравнивать разность между отметками и текущим временем.

В твоем случае, при переходе через границу 2^32 (примерно каждые двое суток), из кеша будут извлекаться не самые последние, а самые старые значения.

На фоне колебаний точности это будет замечательный вечный баг типа «чудо раз в год»...

ly
()
Ответ на: комментарий от anonymous

Это ты видимо так решил сделать, питушочек

nutz ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.