1

Delphi 2010で、ルーチンCopyMemory(内部的にMoveを呼び出す)を使用すると、Moveを使用しているときにそのようなことが発生する可能性があるときに、無効な浮動小数点演算例外が発生することがあります。

アセンブラにデバッグ情報があり、Moveのソースコードを確認しましたが、問題はFILD命令で発生します。問題は、メモリからレジスタ内の浮動小数点に整数値を変換し、その無効な操作をトリガーする可能性があることを発見しました。発生します?私は今2日間これで立ち往生しています

Assembler Information:
; System.Move (Line=0 - Offset=1)
;
00404E0C cmp eax, edx
00404E0E jz System.Move
00404E10 cmp ecx, +$20
00404E13 jnbe System.Move
00404E15 sub ecx, +$08
00404E18 jnle System.Move
00404E1A jmp dword ptr [System.Move+ecx*4]
00404E21 fild qword ptr [ecx+eax]
00404E24 fild qword ptr [eax] ; <-- EXCEPTION
00404E26 cmp ecx, +$08
00404E29 jle System.Move
00404E2B fild qword ptr [eax+$08]
00404E2E cmp ecx, +$10
00404E31 jle System.Move
00404E33 fild qword ptr [eax+$10]
00404E36 fistp qword ptr [edx+$10]
00404E39 fistp qword ptr [edx+$08]
00404E3C fistp qword ptr [edx]
00404E3E fistp qword ptr [ecx+edx]

Registers:
EAX: 0E3A4694 EDI: 0000000D
EBX: 00001B5C ESI: 0ECF7928
ECX: 00000005 ESP: 0612FC1C
EDX: 0E3A2B38 EIP: 00404E24

そのエラーの原因は何ですか?

4

2 に答える 2

6

この問題は以前にも見たことがあります。問題は、Move メソッドに入る前に、x87 レジスタのスタックが空ではなく、無効な浮動小数点値を含んでいたことでした。これは、以前に発生した例外が原因で、x87 スタックがそのまま残っていました。

Move コマンドは x87 レジスタを使用します。これは、SSE 命令に依存せずにデータを高速に移動できるためですが、スタックが空であることを前提としています。

解決策を見つける:

  • Move コマンドの開始時にブレークポイントを設定し、FPU デバッグ ウィンドウを使用して、FPU スタックが実際に破棄されていることを確認します。
  • ここから: アプリケーションのどこで、同じウィンドウを使用して FPU スタックが破棄された原因となったかをバックトレースします。これが問題の原因です。
于 2012-07-06T16:05:12.957 に答える
1

以前に発生した問題に似ているようです: 8087CW モードの変更による System.Move のメモリ破損 (png + stretchblt)

私の修正は、FastMove.pas の SSE/MMX を無効にすることでした。そのため、FPU を (誤) 使用しなくなりました (FPU の破損に対して脆弱ではなくなりました)。

于 2012-07-06T20:35:41.247 に答える