Я имею странный проблема повреждения памяти. После многих часов, отлаживая и пробуя я думаю, что нашел что-то.
Например: Я делаю присвоение простой строки:
sTest := 'SET LOCK_TIMEOUT ';
Однако результат иногда становится:
sTest = 'SET LOCK'#0'TIMEOUT '
Так, _ заменяется на 0 байтов.
Я видел этот случай однажды (репродуцирование хитро, зависит от синхронизации) в Системе. Переместите функцию, когда она будет использовать стек FPU (поле, 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 и 2 представления отладки памяти (Delphi-> Представление-> Отладка-> ЦП-> Память) я видел, что он шел не так, как надо..., после того как... не мог воспроизвести однако...
Этим утром я считал что-то о 8087CW режим, и да, если это изменяется в 27$ F, я получаю повреждение памяти! Обычно это - 133$ F:
Различие между 133$ F и 027$ F - то, что 027$ F настраивают FPU для того, чтобы сделать менее точные вычисления (ограничивающий для Удвоения в земельном участке Расширенных) и другая обработка инфинити (который использовался для более старого FPU, но больше не используется).
Хорошо, теперь я нашел почему, но не когда!
Я изменил работу своего AsmProfiler с простой проверкой (таким образом, все функции проверяются в, входят и уезжают):
if Get8087CW = $27F then //normally $1372?
if MainThreadID = GetCurrentThreadId then //only check mainthread
DebugBreak;
Я "представил" некоторые единицы и dll's и бинго (см. стек):
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)? Или Система. Переместить функцию, не отказоустойчивую?
Примечание: просто попытка воспроизвести не работает:
Set8087CW($27F);
sSQL := 'SET LOCK_TIMEOUT ';
Это, кажется, более экзотично... Но debugbreak на 'Get8087CW = 27$ F' я мог воспроизвести его на другой строке: часть 1 FPU: часть 2 FPU: часть 3 FPU: Финал FPU: повреждение!:
Примечание 2: Возможно, стек FPU должен быть очищен в Системе. Переместиться?
Я не видел этой конкретной проблемы, но Move определенно может испортиться, если FPU находится в плохом состоянии. Драйвер Cisco VPN может ужасно облажаться, даже если вы не делаете ничего, связанного с сетью.
http://brianorr.blogspot.com/2006/11/intel-pentium-d-floating-point-unit.html [сломанный]
https://web.archive.org/web /20160601043520/http://www.dankohn.com/archives/343
http://blog.excastle.com/2007/08/28/delphi-bug-of-the-day-fpu-stack-leak / (комментарии Ричи Аннанда)
В нашем случае мы обнаруживаем неисправный драйвер VPN и заменяем Move и FillChar версиями Delphi 7, заменяем IntToStr версией Pascal (версия Int64 использует FPU) и , поскольку мы используем FastMM, мы также отключаем его пользовательские процедуры перемещения фиксированного размера, поскольку они даже более уязвимы, чем System.Move.
Это может быть ошибка в вашем видеодрайвере, которая не сохраняет управляющее слово 8087 при выполнении операции StretchBlt.
Раньше я наблюдал подобное поведение при использовании определенных драйверов принтера. Они думают, что владеют 8087 CW, и ошибаются ...
Обратите внимание, что значение по умолчанию для 8087 CW в Delphi кажется 1372 $; для более подробного объяснения значений CW см. в этой статье : в ней также объясняется ситуация, которую Майкл Джастин описал, когда его 8087CW попал под шланг.
- jeroen