У меня странная проблема с повреждением памяти.После многих часов отладки и попыток, я думаю, что-то нашел.
Например: я делаю простое строковое присваивание:
sTest := 'SET LOCK_TIMEOUT ';
Однако результат иногда становится:
sTest = 'SET LOCK'#0'TIMEOUT '
Итак, _ заменяется на 0 байт.
Я видел, как это происходило один раз (воспроизведение сложно, зависит от синхронизации) в функции System.Move, когда она использует стек FPU (fild, fistp) для быстрого копирования памяти (в случае с 9 до 32байт для перемещения):
...
@@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 и двух представлений отладки памяти (Delphi -> View -> Debug -> CPU -> Memory) Я видел, что происходит не так ... один раз ...однако не удалось воспроизвести ...
Этим утром я прочитал кое-что о режиме 8087CW, и да, если это изменить на $ 27FI, получит повреждение памяти!Обычно это $ 133F:
Разница между $ 133F и $ 027F состоит в том, что $ 027F устанавливает FPU для выполнения менее точных вычислений (ограничение Double вместо Extended) и другой обработки бесконечности (который использовался для старых 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 Final: повреждено !:
Примечание 2: Может быть, стек FPU должен быть очищен в System.Move?