Повреждение памяти в Системе. Переместитесь из-за измененного 8087CW режим (png + stretchblt)

Я имею странный проблема повреждения памяти. После многих часов, отлаживая и пробуя я думаю, что нашел что-то.

Например: Я делаю присвоение простой строки:

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:FPU part 1 часть 2 FPU:FPU part 2 часть 3 FPU:FPU part 3 Финал FPU: повреждение!: FPU Final: corrupt!

Примечание 2: Возможно, стек FPU должен быть очищен в Системе. Переместиться?

24
задан Kromster says support Monica 22 April 2013 в 12:01
поделиться

2 ответа

Я не видел этой конкретной проблемы, но 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.

9
ответ дан 29 November 2019 в 00:25
поделиться

Это может быть ошибка в вашем видеодрайвере, которая не сохраняет управляющее слово 8087 при выполнении операции StretchBlt.
Раньше я наблюдал подобное поведение при использовании определенных драйверов принтера. Они думают, что владеют 8087 CW, и ошибаются ...

Обратите внимание, что значение по умолчанию для 8087 CW в Delphi кажется 1372 $; для более подробного объяснения значений CW см. в этой статье : в ней также объясняется ситуация, которую Майкл Джастин описал, когда его 8087CW попал под шланг.

- jeroen

3
ответ дан 29 November 2019 в 00:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: