23 votos

De corrupción de memoria en el Sistema.Mover debido a cambiado 8087CW modo png (+ stretchblt)

Tengo un extraño problema de corrupción de memoria. Después de muchas horas de depuración y tratando de que yo creo que he encontrado algo.

Por ejemplo: tengo que hacer una cadena simple de asignación:

sTest := 'SET LOCK_TIMEOUT ';

Sin embargo, el resultado a veces se convierte en:

sTest = 'SET LOCK'#0'TIMEOUT '

Así, el _ sustituido por un 0 bytes.

He visto que esto suceda una vez (reproducción es complicado, depende de la medida del tiempo) en el Sistema.Función mover, cuando se utiliza la FPU de la pila (fild, fistp) para una rápida copia de la memoria (en el caso de 9 a 32 bytes que se mueva):

...
@@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}
...

El uso de la FPU vistas y 2 de la memoria vistas de depuración (Delphi -> Ver -> Debug -> CPU -> Memoria) yo lo vi mal... una vez... no podría reproducirse sin embargo...

Esta mañana he leído algo acerca de la 8087CW modo, y sí, si esto se convierte en $27F puedo obtener de corrupción de memoria! Normalmente es de $133F:

La diferencia entre $133F y $027F es que $027F establece la FPU para hacer menos cálculos precisos (que limita a dos en lugar de Extended) y de diferentes infiniti manejo (que fue utilizado para mayores FPU, pero no se usa más).

Bueno, ahora que he encontrado el por qué pero no se cuando!

He cambiado el trabajo de mi AsmProfiler con una simple comprobación, de manera que todas las funciones son controlados en entrar y salir):

if Get8087CW = $27F then    //normally $1372?
  if MainThreadID = GetCurrentThreadId then  //only check mainthread
    DebugBreak;

I "perfil" de algunas unidades y la dll y bingo (véase la pila):

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))

Por lo que está sucediendo en StretchBlt...

¿Qué hacer ahora? Es un fallo de Windows, o un error en PNG (incluido en D2007)? O es el Sistema.Se mueven en función a prueba de fallos?

Nota: simplemente tratando de reproducir no funciona:

  Set8087CW($27F);
  sSQL := 'SET LOCK_TIMEOUT ';

Parece ser más exótico... Pero por debugbreak en 'Get8087CW = $27F" yo podría reproducir en otra cadena: FPU parte 1: FPU part 1 FPU parte 2: FPU part 2 FPU parte 3: FPU part 3 FPU Final: corruptos!: FPU Final: corrupt!

Nota 2: tal vez la FPU de la pila deben ser liquidadas en el Sistema.Mover?

8voto

Craig Peterson Puntos 8484

No he visto este tema en particular, sino que se Mueven sin duda puede llegar en mal estado si la FPU se encuentra en mal estado. Cisco VPN conductor puede tornillo cosas horriblemente, incluso si usted no está haciendo nada relacionado con la red.

http://brianorr.blogspot.com/2006/11/intel-pentium-d-floating-point-unit.html

http://www.dankohn.com/archives/343

http://blog.excastle.com/2007/08/28/delphi-bug-of-the-day-fpu-stack-leak/ (comentarios por Ritchie Annand)

En nuestro caso tenemos que detectar el buggy controlador VPN y cambiar Mover y FillChar con el Delphi 7 versiones, reemplazar IntToStr con un Pascal versión (Int64-versión utiliza el FPU), y, ya que estamos usando FastMM, podemos deshabilitar su costumbre de tamaño fijo mover las rutinas demasiado, ya que son más susceptibles de Sistema.Mueva.

3voto

Podría ser un error en el controlador de vídeo que no conserva el 8087 de la palabra de control cuando se realiza la StretchBlt operación.
En el pasado he visto un comportamiento similar cuando se utilizan ciertos controladores de impresora. Ellos piensan que son los dueños de la 8087 CW y se equivoca...

Nota: el valor predeterminado de la 8087 CW en Delphi parece $1372; para una explicación más detallada de la CW valores, consulte este artículo: también explica una situación en la que Michael Justin se describe cuando su 8087CW consiguió una manguera.

--jeroen

2voto

André Puntos 4491

Sólo para su información (en caso de que alguien mas tiene el mismo problema): se realizó una actualización de nuestro software para un cliente, y la completa pantalla táctil encerrado cuando nuestra aplicación se inició! Windows estaba completamente congelado! El pc se reinicia (apagado). Tomó algún tiempo para averiguar la causa de la completa congelar.

Por suerte hemos tenido uno (sólo 1!) stacktrace de un AV en FastMove.LargeSSEMove. He desactivado el uso de la ESS en fastmove, y el problema se ha ido.

Por cierto: pantalla táctil dispone de una VÍA Nehemías cpu con un conjunto de chips S3.

Así que no sólo se puede obtener de la memoria de las corrupciones cuando el uso de la FPU, sino también una completa congelar!

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X