GetTickCount() がラップするとどうなりますか?

ドキュメントから:

ただし、DWORD は署名されていないため、問題ありません。 0 - 「非常に大きな数」 =「小さな数」 (もちろん、オーバーフロー チェックがアクティブになっていないと仮定します)。負の数を取得することを示唆する以前の編集がありましたが、それは DWORD が署名されていないことを考慮する前のことでした。

操作に すぐ かかる場合は、まだ問題があります。 しかし49.7日。それはあなたにとって問題ではないかもしれません;)

テストする 1 つの方法は、GetTickCount() をスタブ化することです。 メソッドを使用して、明示的にラップするユニット テストを記述できるようにします。繰り返しますが、本当に算術部分だけを疑っているのであれば、そのための単体テストを簡単に書くことができます:) 本当に、数値がシステムクロックから来ているという事実は、あなたがそのときの振る舞いを知っている限り、ほとんど無関係です.ラップ - これはドキュメントで指定されています。


次の場合に限り、悪いことは何も起こりません:

    <リ>

    DWORD を引きます 最初に他の型に変換するのではなく、

    <リ>

    49.7 日以上かかるものはありません。

これは、符号なし算術オーバーフローが C で明確に定義されており、ラッピング動作がまさに私たちが望んでいることを行うためです。

DWORD t1, t2;
DWORD difference;

t1 = GetTickCount();
DoSomethingTimeConsuming();
t2 = GetTickCount();

t2 - t1 GetTickCount であっても正しい値を生成します 包み込みます。 t2 を変換しないでください および t1 他のタイプ (例:int または double ) 減算を行う前に。

プログラミング言語がオーバーフローをエラーとして扱う場合、これは機能しません。 DoSomethingTimeConsuming() の場合も機能しません 49.7日以上かかります。 t2 を見ただけではわかりません および t1 何回 GetTickCount 残念ながら、ラップアラウンド。

ラップアラウンドが発生しない通常のケースから始めましょう:

t1 = 13487231
t2 = 13492843

ここでは、t2 - t1 = 5612 、これは操作に約 5 秒かかったということです。

ここで、短時間の操作を考えてみますが、GetTickCount は 折り返しました:

t1 = 4294967173
t2 = 1111

操作には 1234 ミリ秒かかりましたが、タイマーはラップアラウンドし、1111 - 4294967173 -4294966062 の偽の値です .

モジュロ 2 32 、減算の結果もラップアラウンドします:

(DWORD)-4294966062 == (DWORD)1234

最後に、操作にほぼかかるエッジケースを考えてみましょう 2 32 ミリ秒ですが、完全ではありません:

t1 = 2339189280
t2 = 2339167207

ここでは、GetTickCount ぐるぐる回り、元の場所に戻ってきました。

現在 t2 - t1 4294945223 という偽物のように見える値を生成します .これは、操作に実際にかかった時間だからです!

一般的に:

(base + offset) - base ≡ offset mod 2^32

GetTickCount() のときに何が起こるかをテストしたい場合 ラップすると、Application Verifier の TimeRollOver テストを有効にできます。

ソフトウェア開発ライフサイクル内でアプリケーション検証ツールを使用することから: