Tengo un extraño problema de corrupción de memoria. Después de muchas horas de depuración e intento, creo que encontré algo.Corrupción de la memoria en System.Move debido a un cambio en el modo 8087CW (png + stretchblt)
Por ejemplo: hago un simple asignación de cadena:
sTest := 'SET LOCK_TIMEOUT ';
Sin embargo, el resultado veces se convierte en:
sTest = 'SET LOCK'#0'TIMEOUT '
Así, el _ es reemplazado por un 0 bytes.
He visto esto una vez (la reproducción es complicada, depende del tiempo) en la función System.Move, cuando utiliza la pila FPU (fild, fistp) para la copia de memoria rápida (en el caso de 9 hasta 32 bytes mover):
...
@@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}
...
Usando la vista FPU y 2 vistas de depuración de memoria (Delphi -> Ver -> depuración -> CPU -> memoria) vi que va mal ... una vez ... no podía reproducirse sin embargo ...
Esta mañana he leído algo sobre el modo 8087CW, y sí, si esto se cambia a $ 27FI ¡se daña la memoria! Normalmente es $ 133f:
La diferencia entre $ 133f y $ 027F es que $ 027F establece la FPU para hacer cálculos menos precisos (limitando a dobles en lugar de extendido) y gastos de envío diferente Infiniti (que fue utilizado para FPU anteriores, pero ya no se usa).
bien, ahora he encontrado la razón por pero no cuando !
he cambiado el trabajo de mi AsmProfiler con una sencilla comprobación (por lo que todas las funciones se controlan a entrar y salir):
if Get8087CW = $27F then //normally $1372?
if MainThreadID = GetCurrentThreadId then //only check mainthread
DebugBreak;
I "perfilado" algunas unidades y DLL y bingo (ver 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 error de Windows o un error en PNG (incluido en D2007)? ¿O la función System.Move no es a prueba de fallas?
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' que pueda reproducirla en una otra cadena : FPU parte 1: FPU parte 2:
FPU parte 3:
FPU final: corrupto !:
Nota 2: Quizás la pila de FPU se debe borrar en System.Move?
+1 por el buen trabajo en la investigación. No sé la respuesta, pero mi estrategia de solución de problemas siempre es simplificar el problema eliminando las posibilidades. Vea si puede gobernar el PNG dentro o fuera eliminándolo o reemplazándolo con una lib más nueva. –
Pregunta relacionada: http://stackoverflow.com/questions/1466229/what-can-cause-system-move-to-occasionaly-give-wrong-results – mghie