奇妙なメモリ破損の問題があります。何時間もデバッグして試した後、何かを見つけたと思います。
例: 簡単な文字列割り当てを行います。
sTest := 'SET LOCK_TIMEOUT ';
ただし、結果が次のようになる場合があります。
sTest = 'SET LOCK'#0'TIMEOUT '
したがって、_ は 0 バイトに置き換えられます。
System.Move 関数で、高速メモリ コピーに FPU スタック (fild、fistp) を使用する場合 (9 バイトから 32 バイトまで移動する場合)、これが 1 回発生するのを見たことがあります (タイミングによっては、再現が難しい場合があります)。
...
@@SmallMove: {9..32 Byte Move}
fild qword ptr [eax+ecx] {Load Last 8}
fild qword ptr [eax] {Load First 8}
cmp ecx, 8
jle @@Small16
fild qword ptr [eax+8] {Load Second 8}
cmp ecx, 16
jle @@Small24
fild qword ptr [eax+16] {Load Third 8}
fistp qword ptr [edx+16] {Save Third 8}
...
FPU ビューと 2 つのメモリ デバッグ ビュー (Delphi -> View -> Debug -> CPU -> Memory) を使用すると、うまくいかないことがわかりました...一度...再現できませんでしたが...
今朝、私は 8087CW モードについて何か読みました。はい、これを $27FI に変更すると、メモリが破損します! 通常は $133F です。
$133F と $027F の違いは、$027F が FPU を設定して、精度の低い計算 (Extended ではなく Double に制限) と、異なる無限処理 (古い FPU で使用されていましたが、現在は使用されていません) を行うことです。
さて、理由はわかりましたが、いつではありません!
簡単なチェックでAsmProfilerの動作を変更しました(そのため、すべての関数は出入り時にチェックされます)。
if Get8087CW = $27F then //normally $1372?
if MainThreadID = GetCurrentThreadId then //only check mainthread
DebugBreak;
いくつかのユニットと dll とビンゴを「プロファイリング」しました (スタックを参照):
Windows.StretchBlt(3372289943,0,0,514,345,4211154027,0,0,514,345,13369376)
pngimage.TPNGObject.DrawPartialTrans(4211154027,(0, 0, 514, 345, (0, 0), (514, 345)))
pngimage.TPNGObject.Draw($7FF62450,(0, 0, 514, 345, (0, 0), (514, 345)))
Graphics.TCanvas.StretchDraw((0, 0, 514, 345, (0, 0), (514, 345)),$7FECF3D0)
ExtCtrls.TImage.Paint
Controls.TGraphicControl.WMPaint((15, 4211154027, 0, 0))
だから、それは StretchBlt で起こっています...
今何をする?Windows のせいですか、それとも PNG のバグですか (D2007 に含まれています)。または、System.Move 関数はフェイルセーフではありませんか?
注:単純に再現しようとしてもうまくいきません:
Set8087CW($27F);
sSQL := 'SET LOCK_TIMEOUT ';
それはもっとエキゾチックなようです...しかし、「Get8087CW = $27F」のデバッグブレークにより、別の文字列で再現できました: FPU パート 1:
FPU パート 2:
FPU パート 3:
FPU 最終: 破損!:
注 2: System.Move で FPU スタックをクリアする必要があるのではないでしょうか?