Ce qui se passe quand GetTickCount() enveloppe?
Si un thread est en train de faire quelque chose comme ceci:
const DWORD interval = 20000;
DWORD ticks = GetTickCount();
while(true)
{
DoTasksThatTakeVariableTime();
if( GetTickCount() - ticks > interval )
{
DoIntervalTasks();
ticks = GetTickCount();
}
}
Finalement, les tiques va envelopper lorsque la valeur ne correspond pas à une valeur DWORD.
J'ai discuté avec un collègue. L'un d'entre nous croit que le code se comportent encore 'bien' quand l'écharpe se produit, car la soustraction de l'opération sera également envelopper. L'autre d'entre nous, estime qu'il ne fonctionne pas toujours, surtout si l'intervalle est grand.
Qui de droit, et pourquoi?
Grâce.
Ce que vous êtes vraiment poser est de savoir ce qui se passe lorsque vous soustrayez un grand DWORD de un petit. Vous et votre collègue pourrait ont écrit un programme pour trouver. GetTickCount est pas pertinente pour.
J'ai fait l'expérience avec calc.exe, mis à la mode hex à l'aide dword taille. Et les résultats regardé comme il se comporte bien... cependant, mon collègue n'était pas convaincu que cela fonctionnerait dans tous les cas, donc la question. GetTickCount est pertinente, Jon Skeet déjà souligné, nous pourrions utiliser GetTickCount64 au lieu
GetTickCount64() modifie l'ampleur du problème à l'emballage après quelque chose comme 200 milliards de jours.... êtes-vous sûr que votre code ne s'exécute pas longtemps? 😉
J'ai fait l'expérience avec calc.exe, mis à la mode hex à l'aide dword taille. Et les résultats regardé comme il se comporte bien... cependant, mon collègue n'était pas convaincu que cela fonctionnerait dans tous les cas, donc la question. GetTickCount est pertinente, Jon Skeet déjà souligné, nous pourrions utiliser GetTickCount64 au lieu
GetTickCount64() modifie l'ampleur du problème à l'emballage après quelque chose comme 200 milliards de jours.... êtes-vous sûr que votre code ne s'exécute pas longtemps? 😉
OriginalL'auteur Scott Langham | 2009-04-07
Vous devez vous connecter pour publier un commentaire.
De les docs:
Cependant, DWORD est pas signé - alors vous devriez être bien. 0 - "très grand nombre" = "petit nombre" (en supposant que vous n'avez pas de vérification de dépassement actif, bien sûr). J'ai eu une édition précédente qui a suggéré que vous obtenez un nombre négatif, mais c'était avant que j'ai pris en compte que DWORD est pas signé.
Vous aurez toujours un problème si l'opération prend juste sous 49,7 jours. Qui peut ne pas être un problème pour vous 😉
Un moyen pour tester serait de stub les
GetTickCount()
méthode de sorte que vous pourriez écrire des tests unitaires, où vous faire explicitement renvoyer à la ligne. Et puis, si vous êtes vraiment seulement douter de l'arithmétique partie, vous pouvez facilement écrire des tests unitaires pour ça 🙂 Vraiment, le fait que le nombre est à venir à partir d'un système d'horloge est à peu près hors de propos tant que vous savez sur le comportement lors de l'enveloppe et c'est indiqué dans la documentation.OriginalL'auteur
Rien de mauvais ne se passe, tant que:
Vous soustrayez
DWORD
s, plutôt que d'opter pour un autre type de premier.Rien de ce que vous essayez de temps prend plus de temps que 49,7 jours.
C'est parce que unsigned de dépassement de capacité arithmétique est bien définie dans C, et le comportement d'habillage est exactement ce que nous voulons.
t2 - t1
de produire l'corriger la valeur, même siGetTickCount
s'enroule autour de. Il suffit de ne pas convertirt2
ett1
à un autre type (par exemple,int
oudouble
) avant de faire la soustraction.Cela ne fonctionnera pas si le langage de programmation traite de débordement comme une erreur. Il aussi de ne pas travailler si
DoSomethingTimeConsuming()
prend plus de temps que 49,7 jours. Vous ne pouvez pas dire tout simplement en regardantt2
ett1
combien de foisGetTickCount
enroulé autour, malheureusement.Commençons avec le cas habituel, où aucun enveloppante entre en jeu:
Ici,
t2 - t1 = 5612
, ce qui signifie que l'opération a pris environ cinq secondes.Maintenant envisager une opération qui prend un peu de temps, mais où
GetTickCount
ne s'enrouler autour de:L'opération a pris 1234ms, mais la minuterie enroulé autour, et
1111 - 4294967173
est le faux la valeur de-4294966062
. Toujours à quoi allons-nous faire?Bien, modulo 232, le résultat de la soustraction s'enroule autour de, trop:
Enfin, considérons le cas limite où une opération de près de 232 millisecondes, mais pas tout à fait:
Ici,
GetTickCount
enroulé autour, et fit demi-tour autour de l'endroit où il était.Maintenant
t2 - t1
les rendements les faux-la recherche de la valeur de4294945223
. C'est parce que c'est la quantité de temps que l'opération a effectivement eu!En général:
OriginalL'auteur
Si vous voulez tester ce qui se passe quand
GetTickCount()
wraps, vous pouvez activer l'Application du Vérificateur TimeRollOver test.De Utilisez Le Vérificateur D'Applications Au Sein De Votre Cycle De Développement De Logiciel:
OriginalL'auteur
Je suggère le calcul de la vraie période écoulée entre les deux tiques, en ne s'appuyant pas sur le compilateur gère pour vous:
OriginalL'auteur
J'ai couru à travers ce problème récemment. Le code que je travaillais sur GetTickCount() dans un tas d'endroits pour déterminer si le programme a été de passer trop de temps sur une tâche particulière et si oui il serait temps que tâche et re-programmer pour une exécution ultérieure. Qu'arriverait-il, c'est que si la GetTickCount() enveloppé pendant l'une des périodes de mesure, le code de temps prématurément. C'était un service qui fonctionne en permanence, de sorte que tous les 49 jours, il aurait un léger hoquet.
Je l'ai fixée par l'écriture d'une classe timer qui a utilisé GetTickCount() à l'intérieur, mais détecté lorsque la valeur enveloppé et indemnisée.
OriginalL'auteur
Un big bang se produit.
Oh, désolé, un big bang des enveloppes.
OriginalL'auteur
Vous pouvez le tester 😉 - j'ai un test simple demande ici qui va lancer une application et crochet
GetTickCount()
en elle de sorte que vous pouvez le contrôler à partir de l'interface graphique de l'application de test. Je l'ai écrit comme déraciner lesGetTickCount()
appels dans certaines applications n'est pas toujours facile.TickShifter est gratuit et est disponible ici: http://www.lenholgate.com/blog/2006/04/tickshifter-v02.html
Je l'ai écrit alors que l'écriture d'une série d'articles sur le Développement Piloté par les tests utilisant des code utilisé
GetTickCount()
une fracture.Articles sont disponibles ici dans le cas où vous êtes intéressé: http://www.lenholgate.com/blog/2004/05/practical-testing.html
Cependant, en résumé, votre code fonctionne...
OriginalL'auteur
Cet article m'a aidé, mais je pense qu'il y a un bug dans:
Quand je l'ai testé ce, à l'envelopper autour du point, j'ai trouvé qu'il était hors de 1.
Ce qui a fonctionné pour moi a été:
OriginalL'auteur
Sûrement, Vous avez besoin pour gérer cette tique, envelopper problème.
Noyau Linux gère la tique envelopper problème avec l'astuce suivante:
L'idée est jeté non signé signé et comparer leur valeur, alors que si le |a-b|<2^30, puis les envelopper n'influence pas le résultat.
Vous pouvez avoir un essai avec ce truc et obtenir de savoir pourquoi cela fonctionne.
Depuis DWORD est également unsigned int, cette astuce devrait fonctionne aussi pour windows.
De sorte que vous code pourrait être qqch comme:
Seulement si l'intervalle de moins de 0 x 2^30, il fonctionne.
OriginalL'auteur