4

D2010でAsyncProを実行しようとしています。SourceForgeの5.00バージョンを使用します。

以下のAsyncProコード(OOMisc.pas内)は、以下のMakeLong行の範囲チェックエラーで失敗しています。これのデバッグを開始する方法がわかりません。

誰かがD2010でASyncProを実行している、または以下で何が起こっているのかについての洞察を持っていますか?私がSourceForgeに投稿しても、応答はありませんでした。

function SafeYield : LongInt;
  {-Allow other processes a chance to run}
var
  Msg : TMsg;
begin
  SafeYield := 0;
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin
    if Msg.Message = wm_Quit then
      {Re-post quit message so main message loop will terminate}
      PostQuitMessage(Msg.WParam)
    else begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
    {Return message so caller can act on message if necessary}
    SafeYield := MAKELONG(Msg.Message, Msg.hwnd);  // Range Check Error on this line!
  end;
end;

TIA

4

4 に答える 4

2

範囲チェックをオンにしてコードをコンパイルしているようです。

{$R+}
function Test(A, B: LongWord): LongInt;
begin
  Result:= MakeLong(A,B);
// Project .. raised exception class ERangeError with message 'Range check error'.
end;

範囲チェックをオフに切り替えてランタイムエラーを取り除くことができますが、

SafeYield := MAKELONG(Msg.Message, Msg.hwnd)

引数の1つ(または両方)が2 ^ 16-1を超える場合は、正しくありません。

コードは16ビットのAsyncProバージョンから32ビットバージョンに変更せずに移植されたようで、バグはすべての32ビットAsyncProバージョンのどこにでも存在していました。

于 2010-12-09T05:34:51.897 に答える
1

MAKELONGがWord型(16ビット)の2つのパラメーターを取り、Msg.MessageとMsg.HWndが両方とも32ビットであると考えると、範囲チェックエラーが発生するのは当然のことです。一般に、ウィンドウメッセージは8000ドル未満なので、値が問題になるとは思えません。ただし、HWndの積分値はマップ全体に存在する可能性があり、確かに>$FFFFであることがよくあります。このため、上記のコードは、16ビットバージョンからの古くから残っているアーティファクトであるように見えることを除いて、実際には意味がありません。

範囲チェックが有効になっているので、上記のコードを少し再考する必要があるという事実を明確に強調しています。Win32では、メッセージ値とウィンドウハンドルを32ビットに収めることができなくなりました。

進め方についていくつかのヒントをお伝えしたいと思います。この関数を呼び出すコードを考慮しないと、代替の実装を提案することはできません。

于 2010-12-09T05:09:02.540 に答える
1

アレンのコメントをエコーし​​ますが、さらに進んでください。コードがどのように使用されているかを見ると(OoMiscでもDelayTicksを見てください)、呼び出し元は戻り値が重要でないと見なすか、単なるメッセージであると見なします。Msg.hwndを番号に追加しても、機能しないだけでなく、発信者が期待していることでもありません。

repeat
  if Yield then
    Res := SafeYield;
until (**Res = wm_Quit**) or TimerExpired(ET);

このコードはメッセージのみを想定しています。

行を変更します

 SafeYield := MAKELONG(Msg.Message, Msg.hwnd);

 SafeYield := Msg.Message;
于 2011-01-10T22:35:03.633 に答える
0

(1)そのコードはメッセージポンプであり、

(2)(コンテキスト内で)R-コンパイラ指令によって保護されています。範囲チェックがオフになっています:AwDefine.incの{$R-範囲チェックなし}

したがって、(1)他のメッセージによってコードが停止した場合、これはメッセージが通過するときの場所であり、

(2)ここからレンジチェックエラーは発生しません。

これは、非同期プロセスが範囲チェック例外またはモーダルメッセージを引き起こしていることを示しています。私が使用しているDelphiのバージョンでは、範囲チェックエラー(およびリストインデックスメッセージ)はソース/デバッグ情報を提供しないため、エラーが非同期のCommイベント、または取得したイベントにリンクされている可能性があることを示唆することしかできません。フォーカス/ロストフォーカス/アクティブ化/ペイントイベント。

于 2013-09-03T08:52:08.143 に答える