10
votes

Delphi: Comment éviter le déroulement d'Eintoverflow lors de la soustraction?

Microsoft dit déjà, dans la documentation pour GettickCount, que vous ne pouviez jamais comparer les comptes de coche pour vérifier si un intervalle est passé. E.G.:

p> xxx pré>

Le code ci-dessus est mauvais car il est uceptable pour le renversement du compteur de tiques. Par exemple, supposons que l'horloge est proche de l'extrémité de sa plage: p> xxx pré>

alors vous effectuez votre chèque: p> xxx pré>

Ce qui est satisfait immédiatement, puisque gettickcount code> est strong> plus grand que de terminé code>: p> xxx pré>


La solution h2>

à la place, vous devez toujours soustraire les intervalles de deux fois: p> xxx pré>

regardant le même math: p> xxx pré>

qui est bien et bien en C / C ++, où le compilateur se comporte d'une certaine manière. P>

mais qu'en est-il de Delphi? H2>

mais quand j'effectue le Même maths dans Delphi, avec débordement vérifiant sur ( {q +} code>, {$ overflowchecks sur} code>), la soustraction des deux numéros de tick génère une exception EintoverFlow lorsque le TickCount em> roule sur: p> xxx pré>

Quelle est la solution souhaitée pour ce problème? P>

EDIT: J'ai essayé de désactiver temporairement overflowchecks code>: p> xxx pré>

mais la soustraction jette toujours un eintoverflow c ode> exception. p>

existe une meilleure solution, impliquant des moules et des types de variables intermédiaires plus importants? P>


Mise à jour H2>

Une autre question que j'ai demandé a expliqué pourquoi j'ai expliqué pourquoi {$ overflowchecks} code> ne fonctionne pas. Apparemment, cela ne fonctionne que sur le niveau niveau fort>, pas le niveau line fort>. Ainsi, tandis que les suivants ne fonctionnent pas forts> travail: p> xxx pré>

Le texte suivant fait strong> travail: p>

delta := Subtract(GetTickCount, startTime);

{$OVERFLOWCHECKS OFF}]
   function Subtract(const B, A: DWORD): DWORD;
   begin
      Result := (B - A);
   end;
{$OVERFLOWCHECKS ON}


0 commentaires

4 Réponses :


1
votes

Vous pouvez utiliser le type de données INT64 pour éviter le débordement: xxx


1 commentaires

Votre échantillon de code d'origine ne fonctionnera pas correctement avec Rollover. Ce code dit que $ FFFFFF00 - $ 000000FF = -4294966785, plutôt que le 511 correct. Le correctif est à et le résultat avec $ FFFFFFFF.



5
votes

J'ai cessé de faire ces calculs partout après avoir écrit quelques fonctions d'assistant appelées à la place.

Pour utiliser le nouveau gettickcount64 () code> fonction sur Vista et plus tard il y a le nouveau type suivant: p>

function GetTicksRemaining(...): TSystemTicks;
function GetElapsedTicks(...): TSystemTicks;
function IsTimeRunning(...): boolean;


1 commentaires

J'ai quelque chose de similaire (gettickcounthp), qui utilise la minuterie haute performance. J'allais dire que le nombre de 64 bits est toujours susceptible de roulement - mais je ne prévois pas d'être sur le point de réparer le bogue dans 580 millions d'années. Je suppose que passer à un compteur de 64 bits est une bonne idée d'aller de l'avant. Mais comme vous l'avez dit, les retombées sur Windows 2000 et XP à Gettickcount quittent toujours le problème initial.



3
votes

Vous pouvez également utiliser dsitimetTime64 à partir du DSIWIN32 :

threadvar
  GLastTimeGetTime: DWORD;
  GTimeGetTimeBase: int64;

function DSiTimeGetTime64: int64;
begin
  Result := timeGetTime;
  if Result < GLastTimeGetTime then
    GTimeGetTimeBase := GTimeGetTimeBase + $100000000;
  GLastTimeGetTime := Result;
  Result := Result + GTimeGetTimeBase;
end; { DSiTimeGetTime64 }


0 commentaires

6
votes

Que diriez-vous d'une simple fonction comme celle-ci? XXX PRE>

Vous avez donc P>

StartTime := GetTickCount
...
if GetElapsedTime(StartTime) > 10000 then
...


1 commentaires

J'aime ce modèle de conception pour résoudre ma situation spécifique. Il s'agit également d'une manière ronde, répondez à la question de savoir comment soustraire sans débordement en utilisant des IFS. En fin de compte, j'ai eu la réponse sur une autre question à ce que {$ OverflowChecks désactivé} ne définit que fonctionner uniquement au niveau de la fonction, non au niveau de la ligne: j'ai donc créé une fonction appelée soustraire (B , A)