Di corruzione della memoria nel Sistema.Muoversi a causa cambiato 8087CW modalità png (+ stretchblt)

StackOverflow https://stackoverflow.com/questions/2584654

  •  24-09-2019
  •  | 
  •  

Domanda

Strano ho un problema di corruzione della memoria.Dopo molte ore di debug e cercando penso di aver trovato qualcosa.

Per esempio:Faccio una semplice stringa di assegnazione:

sTest := 'SET LOCK_TIMEOUT ';

Il risultato, tuttavia, a volte diventa:

sTest = 'SET LOCK'#0'TIMEOUT '

Così, l' _ viene sostituito da 0 byte.

Ho visto che questo accada una volta (riproduzione è difficile, dipende dalla tempistica) nel Sistema.Funzione sposta, quando si utilizza la pila FPU (fild, fistp) per velocità di copia della memoria (in caso di 9 fino a 32 byte di movimento):

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

Utilizza la FPU vista e 2 memory viste di debug (Delphi -> Visualizza -> Debug -> CPU -> Memoria) ho visto andando male...una volta...non poteva riprodurre tuttavia...

Questa mattina ho letto qualcosa sui 8087CW modalità, e sì, se questo è cambiato in $27F ho corruzione della memoria!Normalmente è di $133F:

La differenza tra $133F e $027F è che $027F imposta la FPU per fare meno calcoli precisi (limitando Doppia in vece di Extended) e diversi infiniti gestione (che è stato utilizzato per anziani FPU, ma non viene più usata).

Ok, ora ho trovato perché ma non quando!

Ho modificato il funzionamento del mio AsmProfiler con un semplice controllo (in modo che tutte le funzioni sono controllate a entrare e uscire):

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

I "profilato" alcune unità e le dll e il bingo (vedere stack):

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

Così sta accadendo in StretchBlt...

Cosa fare ora? E ' un errore di Windows, o un bug in PNG (incluso nel D2007)?O è il Sistema.Spostare funzione failsafe?

Nota: semplicemente tentando di riprodurre non funziona:

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

Sembra essere più esotico...Ma da debugbreak su 'Get8087CW = $27F sono in grado di riprodurre su un'altra stringa:FPU parte 1:FPU part 1 FPU parte 2:FPU part 2 FPU parte 3:FPU part 3 FPU Finale:corrotti!:FPU Final: corrupt!

Nota 2: Forse la FPU stack deve essere cancellato nel Sistema.Spostare?

È stato utile?

Soluzione

Non ho visto questo particolare problema, ma Move può sicuramente ottenere incasinato se la FPU è in cattivo stato. il driver VPN di Cisco può rovinare tutto terribilmente, anche se non stai facendo rete tutto ciò che riguarda.

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

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/ (commenti di Ritchie Annand)

Nel nostro caso abbiamo rilevare il driver buggy VPN e sostituire Move e fillchar con le versioni di Delphi 7, sostituire IntToStr con una versione Pascal (Int64-versione utilizza la FPU), e, dal momento che stiamo usando FastMM, abbiamo disable la sua abitudine fissato dimensioni routine spostare troppo, dato che sono ancora più suscettibili di System.Move.

Altri suggerimenti

Potrebbe essere un bug nel driver video che non conserva 8087 parola di controllo quando si esegue il StretchBlt operazione.
In passato ho visto un comportamento simile quando si utilizzano alcuni driver di stampante.Pensano proprio 8087 CW e sono sbagliate...

Nota il valore predefinito di 8087 CW in Delphi sembra $1372;per una spiegazione più dettagliata dei valori CW, vedere questo articolo:si spiega, inoltre, una situazione che Michael Justin descritto quando il suo 8087CW ottenuto va.

--jeroen

Per vostra informazione (nel caso in cui qualche altro ha lo stesso problema troppo): abbiamo fatto un aggiornamento del nostro software per un cliente, e il touchscreen completo bloccato quando è stata avviata la nostra applicazione! Windows è stato completamente congelato! Il pc ha dovuto essere riavviato (spegnimento). C'è voluto del tempo per capire la causa del blocco completo.

Per fortuna abbiamo avuto una (solo 1!) Stacktrace di un AV in FastMove.LargeSSEMove. Ho disabilitato l'utilizzo di SSE in fastmove, e il problema è andato.

A proposito:. Touchscreen ha una CPU VIA Neemia con un chipset S3

Quindi, non solo è possibile ottenere corruzioni di memoria quando si utilizza la FPU, ma anche un congelamento completo!

Per chi ancora interessato a questo: C'è ancora un altro possibile causa di problemi:

Delphi Rio navi ancora con una versione ASM rotto della Move.

ho avuto il piacere di incontrare il bug oggi, per fortuna ho avuto un caso di test riproducibile. Il problema è questo pezzo di codice:

* ***** BEGIN LICENSE BLOCK *****
 *
 * The assembly function Move is licensed under the CodeGear license terms.
 *
 * The initial developer of the original code is Fastcode
 *
 * Portions created by the initial developer are Copyright (C) 2002-2004
 * the initial developer. All Rights Reserved.
 *
 * Contributor(s): John O'Harrow
 *
 * ***** END LICENSE BLOCK ***** *)

// ... some less interesting parts omitted ...

@@LargeMove:
        JNG     @@LargeDone {Count < 0}
        CMP     EAX, EDX
        JA      @@LargeForwardMove

        // the following overlap test is broken
        // when size>uint(destaddr), EDX underflows to $FFxxxxxx, in which case 
        // we jump to @LargeForwardMove even if a backward loop would be appropriate
        // this will effectively shred everything at EDX + size
        SUB     EDX, ECX              // when this underflows ...
        CMP     EAX, EDX              // ... we also get CF=1 here (EDX is usually < $FFxxxxxx)
        LEA     EDX, [EDX+ECX]        // (does not affect flags)
        JNA     @@LargeForwardMove    // ... CF=1 so let's jump into disaster!

        SUB     ECX, 8 {Backward Move}
        PUSH    ECX
        FILD    QWORD PTR [EAX+ECX] {Last 8}
        FILD    QWORD PTR [EAX] {First 8}
        ADD     ECX, EDX
        AND     ECX, -8 {8-Byte Align Writes}
        SUB     ECX, EDX

Riferimenti

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top