すいません。
GetTickCountでリセットされてしまう対策の関数を作成し、使用しています。
特に問題がないと思ったのですが、Over Flowのエラーが出てしまうことがあります。
出るときと出ないときがあるのでげんいんがつかめません…
関数は下記です。
function GetTime(STime: DWORD): DWORD;
Var
Time1,Time2:DWORD;
begin
Time2 := GetTickCount- STime;
if GetTickCount< STime then
begin
Time1 := 4294967295 - STime;
Time2 := GetTickCount+ Time1;
end;
result := Time2;
end;
この関数を使用しているとある処理によっては
「Time2 := GetTickCount- STime;」
の部分でOver Flowのエラーが出ます。
私なりに修正して
function GetTime(STime: DWORD): DWORD;
Var
Time1,Time2,NowTime :DWORD;
begin
NowTime := GetTickCount;
Time2 := NowTime - STime;
if NowTime < STime then
begin
Time1 := 4294967295 - STime;
Time2 := NowTime + Time1;
end;
result := Time2;
end;
としたらエラーは出なくなりました。
ただ、原因がわからないため、ほんとうにこの修正でよいのか、疑問です。
ただエラーが出なくなったというだけなので。
なぜ起こってしまうのかわかるかたいらっしゃいますか?
DWORDのような整数しか範囲が無い型で
小さい数から多き数を引くと
マイナスになるのでオーバーフローが発生しますよ?
オーバーフローのチェック外せば出ませんが
多き->大きい
KHE00221さん
回答ありがとうございます。
確かにDWORDはマイナスの値は範囲ではありませんが、
Time2 := NowTime - STime;
のTime2がマイナスとなってしまう場合Time2の値は0になるのではないでしょうか?
またそれが原因でオーバーフローが発生してしまう場合
修正後にも発生してしまいませんか?
よろしくお願いします。
> Time2がマイナスとなってしまう場合Time2の値は0になるのではないでしょうか?
0にはなりません。実行時エラーか、でなければDWORDにキャストした値(たとえば-1→4294967295)になります。
オーバーフローエラーが出るような状態だと、修正後のコードでも
実際にGetTickCountが巻き戻ったらエラーになりますね。
こんな風になっていないといけないのでは?
NowTime := GetTickCount;
if NowTime < STime then
begin
Time1 := 4294967295 - STime;
Result := NowTime + Time1 + 1; // 4294967295msと0msの間は1ms
end
else
Result := NowTime - STime;
最初のコードでエラーが出て2番目で消えるというのは説明が付けにくいですね。
(エラーが出たのが2つ目や3つ目のGetTickCountの場所なら、その間にカウント値が変わったからだという解釈もできそうですが)
コードを試している間に、オーバーフローチェックの設定を変えたという可能性はないでしょうか?
>出るときと出ないときがあるのでげんいんがつかめません…
GetTickCount って 49.7日までのはずだから
49.7日ぐらいに1回 Time2 := GetTickCount- STime; で
オーバーフローするはずなんだけど
>としたらエラーは出なくなりました。
修正してから 49.7 日たってないんじゃないの?
回答ありがとうございます。
確かにマイナスになるような状況ではDWORDに
Time2 := NowTime - STime;
こうしてしまうのではなくtorさんの言っているように
比較後計算しなくてはいけませんね。
「+ 1; // 4294967295msと0msの間は1ms」
はどういった場合、必要でしょうか?
動作の対象のOSがWindows Vista以降でしたら
GetTickCount64の使用をお勧めします
GetTickCount64
http://msdn.microsoft.com/ja-jp/library/ms724411(v=VS.85).aspx
GetTickCount
http://msdn.microsoft.com/ja-jp/library/cc429827.aspx
> 「+ 1; // 4294967295msと0msの間は1ms」
> はどういった場合、必要でしょうか?
どういった場合というか、
やりたいことはSTime(前回の値)とGetTickCountとの間の経過時間を求めることですよね?
例えば前回の値が4294967295で今回の値が0だったら、その間に1ms経過しているはずです。
元のコードだとその折り返し分を計算に入れていないので、結果が0msになってしまいます。
ちなみにオーバーフローチェックが無効になっているのなら、
ややこしいことを考えずに Result := GetTickCount-STime; で用が足ります。
で、結局チェックは有効、無効どっちになっているのでしょうか?(新規プロジェクトではデフォルトでオフだったと思いますが)
回答ありがとうございます。
「+1」の意味理解できました。
私のほうで回答を見て色々試してみました。
結局、チェックが有効であれば、エラーになってしまうし、
無効であればキャストした値になりますね。
torさんのいわれているとおりのことが確認できました。
今回はオーバーフローチェックをONしてエラーになっていたので、それがわかって勉強になりました。
先に計算を行い、その計算結果から値をいれるやり方で対応したいと思います。
ありがとうございました。
解決です。
ツイート | ![]() |