Страница 1 из 3

Конфликт мышки и не мышки

СообщениеДобавлено: 11.03.2017 19:29:33
vitaly_l
Всем привет,

долго мучился. Никак не мог поймать ошибку, при нажатии на кнопки, 1 раз в 15 или 115 ВДРУГ выскакивала: Invalid floating point operation.
Мышкой всё работает, а с планшетом, что-то там сбоило. Перепробовал, всё, что нашёл, никак не мог поймать где вылетает.
Седьмое чувство подсказало - отключить мышку от батарейки, при работе с планшетом и сбой вроде перестал появляться (пока не видел).

Видимо, когда нажимал на кнопку, стол качался и
мышка параллельно с планшетом - отправляла сигнал, который и вызывал: Invalid floating point operation,
Вылет, был исключительно при кликах на кнопки ( там моего кода нет, всё обрабатывает "FPC|Lazarus" ).

И вот собственно, вопрос: как от такого сбоя защитить? ( моих знаний слишком мало, я даже не представляю: где это там и как работает? )
Это не актуальный вопрос, т.к. мышку легко отключить переключателем, но всё равно интересно. Можно ли защитить программу?

.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 11.03.2017 20:47:48
Cheb
У процессора есть состояние, в зависимости от которого он при переполнении с плавающей точкой либо поднимает исключение, либо возвращает NaN.

Я тоже недавно нарвался на нежданчик: у меня оказывается с 2006 года выставлялся этот флаг, но только на i386. Запустил 64-битную версию - и сразу выяснилось, что у меня этих делений на ноль - как блох на собаке, просто они до этого молча глотались.

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

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 11.03.2017 20:57:35
vitaly_l
Cheb писал(а):Выставь этот флаг - должно помочь.

Я читал про это в топике про 3д движок. Но у меня не этот случай, т.к. и 64 и 32 - всё одинаково. У меня, именно конфликт мышки с графическим пером. Предположительно, когда они единовременно шлют сигнал в систему. И исключительно при нажатии на кнопки. Видимо, от мышки поступает 0 при нажатии, но обрабатывает его код пера, у которого всегда больше ноля, но переменная видимо одна на двоих и поэтому вылетает ошибка. Где это происходит, я даже представить не могу. А может вовсе и не это происходит... Но если мышку отрубить и оставить только перо, то всё работает и не вылетает. Поэтому я решил что конфликт оборудования.

:!: А касаемо нолей их удобно Assert-ом вычислять и блокировать где можно.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 11.03.2017 21:14:17
runewalsh
Попробуй Math.SetExceptionMask([]).

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 09:45:44
Лекс Айрин
Возможно, стоит подумать о переустановке дров на перо и мышку. Ну или хотя бы настроить их. И да, без бубна нельзя управлять мышкой и пером по отдельности, но 2 и более мышки, допустим, должны нормально, без сбоев, подхватываться системой.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 12:23:31
vitaly_l
runewalsh писал(а):Попробуй Math.SetExceptionMask([]).

Нет, там (в коде) всё в норме, я проверял, ноля - никогда не бывает, но SetExceptionMask всё равно потом сделаю, классная функция, спасибо.

Сегодня, установил версию 1.64 + 3.02 и сбой в этом месте на 32 - вроде перестал появляться, но на 64 - планшет сразу отрубает программу, стоит коснуться пером.

Стал рыть в этой части и нарыл, вот что:

В WinHID.pas - объявление вот такое:
Код: Выделить всё
   pRawInput = ^RawInput;
   RawInput = record
      header: RawInputHeader;
   case byte of
      0: (mouse: RawMouse);
      1: (keyboard: RawKeyboard);
      2: (hid: RawHid);
   end;

А в struct.inc, уже вот такое:
Код: Выделить всё
      tagRAWINPUT = record
      header: RAWINPUTHEADER;
      data: record
        case longint of
          0: (mouse: RAWMOUSE);
          1: (keyboard: RAWKEYBOARD);
          2: (hid: RAWHID);
      end;
    end;
    PRAWINPUT = ^tagRAWINPUT;

Судя по всему именно конфликты в версиях модулей, т.к. здесь и там разные объявления, и где-то там в системе, могут быть разные обращения к raw: pRawInput;

Видимо WinHID.pas - устарел для этой версии Лазаруса и FPC, т.к. в предыдущей версии ЭТИ проблемы - явно отсутствовали.

Добавлено спустя 24 минуты 2 секунды:
В WinHID.pas - объявление вот такое:
Код: Выделить всё
   function GetRawInputData(hRawInput: Windows.HANDLE; uiCommand: Windows.UINT; pData: pointer; var pcbSize: Windows.UINT; cbSizeHeader: Windows.UINT): Windows.UINT; stdcall; external user32;


А в func.inc, немнооожечко другое:
Код: Выделить всё
function GetRawInputData(hRawInput: HRAWINPUT; uiCommand: UINT; pData: LPVOID; pcbSize: PUINT; cbSizeHeader: UINT): UINT; external 'user32' name 'GetRawInputData';

UINT меняется на PUINT, но при этом обращение идёт одной и той же библиотеке и функции.

Пришлось заменить объявление:
preparsedSize, rawSize: Windows.UINT;
на
preparsedSize, rawSize: Windows.PUINT;
Иначе не хотел компилировать. Заменил заработало.

В общем, в итоге, похоже программа ГДЕ-ТО получает вместо адреса в памяти, значение нажатия пера (или около того), т.к. в модулях чехарда с объявлениями. Ну и естественно всё рушится. (я так предполагаю).

Добавлено спустя 16 минут 42 секунды:
Принудительно сделал все ссылки на модуль WinHID.pas - всё заработало на обеих версиях 32 и 64. И изначальный сбой вроде пока ещё не вылетал, но он бывает 1 раз в 15-30 минут. Так что поймать его очень сложно. Возможно теперь, всё починилось, т.к. вроде как при тестировании 32 разряда я сбой не смог получить.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 14:50:18
tema
На багтрекер не забудьте это отправить с описанием исправления :)

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 14:56:14
vitaly_l
tema писал(а):На багтрекер не забудьте это отправить с описанием исправления

Ну вообще-то, это наверное - не баг. Кстати у Вас (в проблеме о ShowModal ) может быть примерно такая же ошибка, т.к. по моему мнению, в Вашем случае, к моменту ShowModal - Ваша программа уже порушилась, а Вы ошибочно думаете что она там падает. Так что, поищите возможно и у Вас конфликт модулей, ещё при старте и создании формы№2.

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

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 19:25:00
Cheb
В общем, в итоге, похоже программа ГДЕ-ТО получает вместо адреса в памяти,

О! Вспомнил ещё нежданчикогенератор: когда сам пишешь интерфейс с системой/внешними длл, надо не забывать
Код: Выделить всё
{push}
{$packrecords c}
<объявление твоей записи>
{$pop}

А не то.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 19:35:01
runewalsh
Лол, это не стандартный модуль, я его в тот раз сам понакопипастил из своего кода. Потому что в модуле Windows от 3.0.0 про это будто бы ничего не было. Неважно, кое-что проясню.

В C API нет специальных выходных параметров, вместо них используются указатели. Функция, возвращающая два инта, может быть объявлена как
Код: Выделить всё
void GetXY(int *x, int *y);
и от тебя предполагается обращаться с ней как
Код: Выделить всё
int a, b;
GetXY(&a, &b);

В Pascal var/out параметры — те же указатели под капотом, вплоть до того, что
Код: Выделить всё
function(var x: integer);
бинарно совместима с
Код: Выделить всё
function(x: pInteger);

Таким образом, в Pascal функцию GetXY можно более выразительно импортировать как
Код: Выделить всё
procedure GetXY(out x, y: cint);
В стандартных модулях-заголовочниках иногда тоже так делают (бывает, даже когда в указателе допустим nil...), но не в этот раз.

Используя версию с PUINT, ты должен был передавать не preparsedSize: Windows.PUINT, а @preparsedSize, где preparsedSize: Windows.UINT. Так-то вообще не должно было компилироваться, вот хотя бы на GetMem(preparsedSize) лол.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 12.03.2017 20:35:11
vitaly_l
runewalsh писал(а):Используя оригинальную версию с PUINT, ты должен был передавать не preparsedSize: Windows.PUINT, а @preparsedSize, где preparsedSize: Windows.UINT. Так-то вообще не должно было компилироваться, вот хотя бы на GetMem(preparsedSize)

Да, всё верно, оно не сразу запустилось, я там много всяких вот таких ^ штучек вставлял и потом оно подключилось и планшет фурычил как надо, если в указанном месте делать вот так: GetMem(preparsedSize^), когда Windows.PUINT. А потом решил всё замкнуть на WinHID.pas, т.к. на 64 вылетало.

runewalsh писал(а):это не стандартный модуль, я его в тот раз сам понакопипастил из своего кода. Возможно, зря, раз объявления в модуле Windows уже есть (или мне в них не понравилось что...). Всё равно кое-что проясню.

В модуле Windows, отсутствует важная часть кода, которая есть WinHID.pas, соответственно модуль Windows - не заменяет WinHID.pas.

Но в любом случае, хорошо, что вопрос с WinHID.pas прояснился. Попробую переделать WinHID.pas под модуль Windows, хотя и не факт, что - это более верное решение, т.к. возможно модуль windows - не сможет работать с hid.dll, а они в коде пересекаются. В общем подумаю ( хотя и сейчас всё вроде работает, но один странный вылет всё же был, так что, что-то там ещё осталось или конфликтует ).

Cheb писал(а):О! Вспомнил ещё нежданчикогенератор: когда сам пишешь интерфейс с системой/внешними длл, надо не забывать
{push}
{$packrecords c}
<объявление твоей записи>
{$pop}

Я с dll вообще не работал никогда. В php этого всего нет, я бы без runewalsh сам бы этот модуль не смог бы написать. Правда теперь я уже на 90% разобрался, что там к чему и более менее ориентируюсь, т.к. теперь из модуля видно, что и где искать + на гитхабе статью почитал про подключение джостиков и всего такого. Попробую сделать свой модуль и вставлю туда {push}{$packrecords c} ... {$pop}, заодно узнаю, что это такое: {push}{$packrecords c} ... {$pop}

Добавлено спустя 24 минуты 32 секунды:
Эта директива в модуле есть => {$packrecords c}. Прочитал про них и про эти: {push} {$pop} - теперь везде буду их вставлять <== Спасибо!

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 13.03.2017 07:29:55
Cheb
В модуле Windows, отсутствует важная часть кода, которая есть WinHID.pas

Какой паскаль?
У 2.6.4 в модуле Windows нет многих функций, поскольку он ещё тащил совместимость с Windows 98, но в 3.0.2 они уже есть.
Можно тупо копипастить оттуда. Можно тупо скопипастить в отдельный модуль, подключаемый
{$if FPC_FULLVERSION<30000},my_oldfpc_fix{$endif}

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 13.03.2017 10:16:30
vitaly_l
Cheb писал(а):У 2.6.4 в модуле Windows нет многих функций, поскольку он ещё тащил совместимость с Windows 98, но в 3.0.2 они уже есть.

Я уже почистил модуль WinHID.pas, и теперь - всё беру из модуля windows, кроме вот этих трёх функций:
Код: Выделить всё
   hidapi = 'hid.dll';
   function HidP_GetCaps(PreparsedData: pointer; out Capabilities: HidpCaps): NTSTATUS; stdcall; external hidapi;
   function HidP_GetValueCaps(ReportType: cint; ValueCaps: pHidpValueCaps; var ValueCapsLength: Windows.USHORT; PreparsedData: pointer): NTSTATUS; stdcall; external hidapi;
   function HidP_GetUsageValue(ReportType: cint; UsagePage: Windows.USHORT; LinkCollection: Windows.USHORT; Usage: Windows.USHORT;
      out UsageValue: Windows.ULONG; PreparsedData: pointer; Report: pointer; ReportLength: Windows.ULONG): NTSTATUS; stdcall; external hidapi;             

Поиском поискал, таких функций вроде нет в новом Лазарусе и FPC 3.02. Всё оказалось совместимо и фурычит, вроде нигде не рушится. Но вчера когда стал тестировать программу на новой версии 1.64 - налетел на глюк отладчика у 1.64, думал сбой FPC. Это затормозило тест, т.к. пока выяснилось, про глюк отладчика, пару раз снёс и установил Лазарус.

В общем - теперь уже обратного пути нет. Соответственно, надеюсь мне уже никогда не понадобится, вот эта директива: {$if FPC_FULLVERSION<30000},my_oldfpc_fix{$endif}. Разве что, скомпилировать 1.7 и на нём всё откомпилировать, я им не пользуюсь т.к. в винде получаются 222 мегабайта файл Лазаруса, даже если компилировать с нужными ключами. И + читал на форуме - это никак нельзя обойти, нужно вырезать внешней программой, поэтому я не пользуюсь свн версиями.

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 13.03.2017 11:01:22
pupsik
.к. в винде получаются 222 мегабайта файл Лазаруса
вроде как нормально "стрипуется" в винде транк (лазарь и фпс).
И + читал на форуме - это никак нельзя обойти, нужно вырезать внешней программой, поэтому я не пользуюсь свн версиями.
взять strip.exe из bin fpc и уменьшится размер. Или в настройках лазаря выбрать "стрипованный вариант". Т.е. "Параметры сборки" - "оптимизированная ИДЕ".

Re: Конфликт мышки и не мышки

СообщениеДобавлено: 13.03.2017 11:17:59
vitaly_l
pupsik писал(а):взять strip.exe из bin fpc и уменьшится размер

Если бы там были функции: HidP_GetCaps, HidP_GetValueCaps и HidP_GetUsageValue, то замена имела бы смысл. А так... думаю буду довольствоваться тем что разработчики дали, в качестве текущей версии.

1.62 - работала 100% стабильно, если также или лучше работает 1.64, то мне ничего бОльшего и ненужно. Это станет понятно в течении недели.

.