Chirurgia endoscopică a hipofizei
"Standardul de aur" în chirurgia hipofizară îl reprezintă endoscopia transnazală transsfenoidală. Echipa NeuroHope este antrenată în unul din cele mai mari centre de chirurgie a hipofizei din Europa, Spitalul Foch din Paris, centrul în care a fost introdus pentru prima dată endoscopul în chirurgia transnazală a hipofizei, de către neurochirurgul francez Guiot. Pe lângă tumorile cu origine hipofizară, prin tehnicile endoscopice transnazale pot fi abordate numeroase alte patologii neurochirurgicale. www.neurohope.ro |
utilizarea resurselor: creare si distrugere
Last Updated: Jul 20 2009 01:22, Started by
dotniet
, Jul 17 2009 23:25
·
0
#1
Posted 17 July 2009 - 23:25
Ce poate cauza o eroare de tipul "The block header has been corrupted" in FastMM4?
Edited by ciuly, 18 July 2009 - 10:37.
|
#2
Posted 18 July 2009 - 10:35
e posibil sa incerci sa dezaloci o bucata de memorie de mai multe ori. vezi si tu de unde aloci memoria si apoi cauta ce faci cu ea (ai informatiile in raportul generat de fastmm. la nevoie poti da enable la detalii).
si deoarece trebuie, ma repet: regula de aur: creare resursa; try utilizare resursa; finally distrugere resursa end;indiferent ce anume este resursa aia. ca este un criticalsection.acquire sau deschidere de fisiere sau alocare de memorie, sau creare de obiect, sau alocare un hwnd samd. iar daca vreti sa prindeti orice exceptie, inclusiv a constructorului, evident, toata povestea de mai sus vine bagat intr-un try/except. daca, si DOAR DACA, toate clasele voastre sunt scrise corect, abea atunci puteti scrie ceva de genul creare res1 try creare res2 creare res3 samd utilizare resurse finally distrugere res3 distrugere res2 distrugere res1 end;pt ca daca res3 in situatia de mai sus arunca exceptie la distrugere, bye bye distrugere res2 si 1. ce mai puteti face este sa bagati distrugerile in try/finally. pt ca se intampla sa ai nevoie sa creezi vreo 5-7 resurse intr-o metoda si in acest caz identarea codului se va duce foarte la dreapat daca le bagati pe toate in try./finallyuri separate. asa ca puteti folosi doar unul mare, si ca sa fiti chiar siguri, puneti doar distrugerile in finally-uri like so creare res1 try creare res2 creare res3 samd utilizare resurse finally try distrugere res3 finally try distrugere res2 finally distrugere res1 end; end; end;la partea de distrugere nu te mai doare asa tare ca se identeaza codul prea la dreapta ca stii ca acolo sunt doar distrugeri. iar in ceea ce priveste clasele constructor create inherited; - optional, nu neaparat la inceput (totusi cu grija daca nu e la inceput) depinde de clasa si de constructor. if in doubt, use it creare resursa1 creare resursa2 ... creare resursan destructor destroy; override;// obligatoriu override distrugere resursa1 distrugere resursa2 ... distrugere resursan inherited; !!!! - obligatoriu la sfarsit !! (in foarte rare cazuri e nevoide inainte de sfarsit, si doar daca ai ceva experienta vei stii acest lucru)exact in aceeasi ordine. pt distrugere obiecte sugerez folosirea functiei FreeAndNil daca a:TObject sau descendent a:TObject begin a:=nil; a.free;// sau freeandnil(a); end;NU va genera eroare si nu se va intampla nimic rau. deci sa nu va fie frica ca tot vad o groaza de chestii de genu if assigned(obiect) then obiect.free; este o tampenie. pt ca obiectul ala poate sa nu fie NIL, ci sa aibe o valoare dar obiectul sa fie distrus si atunci se va intampla un AV. si nu vei stii de ce. pe cand daca folosesti freeandnil, daca l-ai distrus odata, a doua oara sigur va fi nil. iar daca primesti un AV cu adresa nil (adica 0 sau un numar mic, care deobicei este adresa metodei in clasa) stii ca il folosesti fie inainte sa il creezi fie dupa ce l-ai distrus (si nu-s multe locuri unde sa cauti chestia asta si macar stii unde sa pui breakpointurile). daca av-u e cu adresa valida atunci mai mult ca sigur obiectul nu e creat sau e distrus dar folosesti o copie a lui aiurea, si iarasi stii unde sa pui breakpointurile. dar altfel, tre sa le pui peste tot. un alt aspect: metoda destroy a unei clase NU ARE VOIE sa arunce exceptii. aviz amatorilor. doar asa va puteti trezi cu memory leakuri sau chiar cu AV-uri si mai ales cu crash-uri (cel mai adesea). in aceeasi idee, daca deschideti un fisier in constructor si il inchideti in destructor (intre noi fie vorba e o prostie sa iti gandesti clasa asa), asigurati-va ca faceti inchiderea intr-un try/except. pt ca daca constructorul esueaza, automat va fi executat destructorul !!! iar daca constructorul nu a apucat sa deschida fisierul, nu aveti ce inchide. la fel faceti la orice dealocare de resurse care poate sa genereze erori. este unul din motivele pt care se prefera utilizarea claselor acolo unde se poate. de ex in loc de File, file of type sau textfile incercati sa folositi TFileStream. samd. ca alternativa frumoasa la try/except este folosirea acelui if assigned(resursa de memorie) sau altor checkuri in functie de resursa in cauza. (dar repet, nu la clase, acolo n-are sens iar pe mine personal ma zgarie pe ochi) deci nu mai scrieti try obiect=create utilizare obiect finally obiect.free end;pt ca destructorul va fi apelat de DOUA ori in cazul in care constructorul esueaza. si n-are sens (mai ales daca nu va asigurati ca destructorul nu arunca exceptii). daca nu ai construit ceva, nu ai ce distruge. mai departe, daca folositi clase care implementeaza interfete, tineti minte ca ele isi numara instantele automat. Prin urmare, mare grija daca puneti un astfel de obiect intr-un tag:=integer(obiect). pt ca NU isi va retine instanta si riscati ca refcountu sa ajunga la 0, sa vi se distruga clasa si apoi voi sa folositi TWhatever(o.tag).metoda si boom, AV. si nu stiti de ce. puneti mana pe un tutorial de COM sau lucrul cu interfetele si invatati sa va manageuiti corect interfetele. daca limbajul permite, nu inseamna ca trebuie sa abuzati de tot felul de smecherii, dar daca tot vreti sa o faceti, macar faceti-o cu cap si intelegeti ce se intampla defapt acolo. si daca tot sunt la interfete, delphi va distruge automat variabilele locale (!) dintr-o metoda/procedura de tip interfete, dynamic arrays si mai stiu eu care. vedeti in help. DAR, asta nu inseamna ca trebuie sa va bazati pe chestia asta. cel mai bine e ca atunci cand faci mizerie sa faci curat dupa tine. note: AV=Access Violation, totusi daca cititi pe aici ar trebui sa stiti asta (am intalnit programatori care habar n-au de prescurtarile de genu.) |
#3
Posted 18 July 2009 - 13:15
ciuly, on 18th July 2009, 10:35, said: a:=nil; a.free;// sau freeandnil(a); Da asta e regula de aur la mine. Probabil ca ar trebui propovaduita ca biblia Nu iti imbunatateste codul cu nimic in sensul functionalitatii insa in caz ca faci prostii ai sanse sa gassti problema mai repede. Quote e posibil sa incerci sa dezaloci o bucata de memorie de mai multe ori. vezi si tu de unde aloci memoria si apoi cauta ce faci cu ea Stiu cum suna mesajul de eroare pt asta Il mai obtin si pe acela din cand in cand. Insa cu FastMM e usor sa-l "prinzi". Eroare asta e mult mai serioasa. Ce am gasit azinoapte pe un forum, un tip care a avut aceeasi eroare a zis ca o avea de la o o linie de cod care incerca sa acceseze o bucata de memorie care a fost alocata gresit. Ceva de genul, memoria era alocata, dar nu destula. var x: TSomething SetLength(X, PSomething); Edited by dotniet, 18 July 2009 - 13:44. |
#4
Posted 18 July 2009 - 18:14
tu ai un stacktrace pt eroare respectiva generate de fastmm. cu acel stacktrace lucrezi. daca mergi la mecanic si il intrebi: "ce anume poate face motorul sa moara subit" abea se abtine sa nu arunce cu ceva dupa tine. sunt enshpe mii de posibilitati.
intr-adevar, cea mai frecventa posibilitate sa primesti eroarea respectiva este cand suprascrii datele puse de fastmm linga memoria alocata. cum? sunt enshpe mii de posibilitati. daca nu te descurci tu cu stacktraceu pai posteaza-l, pune si codu relevant si declaratiile variabilelor in cauza sa putem sa ne dam si noi cu parerea pe ceva concret. ca asa, povesti... |
#5
Posted 19 July 2009 - 15:54
Treaba cu logul e mai dificila. Nu e mereu la fel.
FastMM has detected an error during a FreeMem operation. The block header has been corrupted. The current thread ID is 0xB84, and the stack trace (return addresses) leading to this error is: 402E6F [System][@FreeMem] 4068A8 [System][@DynArrayClear] 405DF9 [System][@FinalizeArray] 405CFD [System][@FinalizeRecord] 4042FB [System][TObject.CleanupInstance] 40423E [System][TObject.FreeInstance] 40460D [System][@ClassDestroy] 4D1A0E [SmplCub.pas][SmplCub][TCubObj.Destroy][127] 40428B [System][TObject.Free] 4149B9 [SysUtils][FreeAndNil] 4DAE6E [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180] Current memory dump of 256 bytes starting at pointer address 7FC85780: 00 00 00 00 69 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 54 56 00 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 56 00 00 1D 00 00 00... ------- Oricum, am incercat sa pun un Addreess breakpoint la $7FC85780, si nu merge. Programul nu se opreste. Breakpoint la adresa $4DAE6, opreste programul aici: for i:= Count-1 downto 0 DO begin x:= TCubObj(Self[i]); FreeAndNil(x); end; Edited by dotniet, 19 July 2009 - 15:57. |
#6
Posted 19 July 2009 - 17:06
dotniet, on 19th July 2009, 16:54, said: 4DAE6E [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180] dotniet, on 19th July 2009, 16:54, said: Oricum, am incercat sa pun un Addreess breakpoint la $7FC85780, si nu merge. Programul nu se opreste. dotniet, on 19th July 2009, 16:54, said: Breakpoint la adresa $4DAE6, opreste programul aici: for i:= Count-1 downto 0 DO begin x:= TCubObj(Self[i]); FreeAndNil(x); end; self[i] e cumva o proprietate property x[index:integer]:cevaclasa/pointer read write; default; ? nu e relevant pt problema dar incerc sa inteleg de ce folosesti self[i] cand self se refera la instanta curenta si e indicat sa o folosesti doar cand ai conflicte de scop ale variabilelor/mebrilor/metodelor in locul tau, din moment ce am o lisat de clase TCubObj as folosi clasa TObjectList din contnrs create cu parametrul freeovjects/ownobjesct sau cum s-o fi numind pe true ceea ce ma asigura ca daca obniectul e distrus sau elementele sunt sterse, vor fi si distruse. deci tot forul tau se oinlocuieste cu un freeandnil(lista:TObjectList) sau lista.clear daca apelul nu e in destructor ci e doar ceva gen clear. motivele pt care primesti eroare se prea poate ca sunt din cauza de conflict de date/tipuri de date. daca presumtia mea ca self[i] este o proprietate array default, atucni ea trebuie sa intoarca un TObject sau un tip integer pe 32 de biti SAU pe 64 de biti daca platforma pe care rulezi este de 64 de biti iar compilatorul iti face integeru poe atatia biti cat e platforma. aviz amatorilor de casting intre integer si pointer, ca pointeru pe 64 de biti are 64 de biti nu 32. dar ma rog, aici sunt detalii ale compilatorului. un simplu showmessage cu sizeof lamureste problema. oricum, atentie la acest mic amanunta. revenind, chiar mi se pare o greseala urata faza cu self[i] mutat intr-o variabila ajutatoare CU cast. in momentul in care vrei sa distrugi niste obiecte ale tale, le vei distruge din containerul propriu care este privat (in sugestia mea containerul este lista:TObjectList) dar poate fi orice (un array, un TList, whatever). gandeste-te ca doebicei proprietatile vor expune pe linga datele respective si niste cod. este un overhead facut degeaba, nemaivorbind de problemele care pto aparea dintr-un astfel de model. sa admitem ca aceasta clasa este threadsafe. din start, accesarea unui element via proprietatea x va avea cel putin un apel la un critical section sau alt mod de sincronizare, pe linga posibilele validari (indexu sa fie in limite, samd)) lucru pe care la o lista de 10000 de elemente, distrugerea iterativa va baga un mare delay degeaba. ----------- pt a gasi raspunsul la intrebarea ta fara sa bagi rezolvarea sugerata de mine (pe care totusi in final ar trebui sa o bagi) pt inceput, trebuie sa stim: - platforma pe care rulezi - platforma pe care compilezi - daca vreunul e pe 64, daca folosesti ceva librarii sau alte hack-uri pt modificarea/optimizarea codului pt platforma pe 64 de biti (sau eventual daca folosesti dll-uri compilate pt aceasta plaforma si faci schimb de date intre ele prin pointer (inclusiv pchar) si/sau integer) - cum se creaza self[i] (toate modurile, inclusiv addition daca e cazul) - cum se distruge self[i] (toate modurile, inclusiv deletion daca e cazul) - daca TCubObj implementeaza interfete ori ba - si in final, ce anume e self[i] si daca are ceva cod in spate, mai mult pt curiozitatea mea foarte util ar fi daca ai putea face un mic demo din aplicatia ta care sa aibe acest behaviour. daca totul la tine e pe 32 de biti iar self[i] este defapt un TObject sau descendent si nu implementeaza vreo interfata, SI valoarea lui self[i] este valida (adica nu te apuci si undeva scrii self[i]:=whatever (fie direct prin self[i] fie prin intermediul containerului) pune un breakpoint in destructorul lui TCubObj (il creezi daca nu exista ) si vezi exact de unde se distruge. daca aplicatia e complicata, atunci optim ar fi sa poti loga stacktraceul (exista mai mutle posibilitati, madexcept, jedi, eureka, samd) o alta modalitate de a verifica validitatea pointerilor este sa pui breakpoint cand adaugi in lista, cand modifici din lista cand stergi din lista si in foru ala al tau. la primu element adaugat, notezi adresa si apoi modifici proprietatile breakpointurilor sa opreasca cand se opereaza cu prima valoare (adica indexu 0, nu valoarea notata). cand intra breakpointu, verifici valoarea din pointer cu ce ai notat inainte si dupa operatie. e probabil ca daca faci ceva gresti pe acolo sa iti dai seama unde si care e probelama. |
#7
Posted 19 July 2009 - 18:41
Bucata de cod e dintr-un obiect derivat din TObjectList.
De aici vine self. Folosesc Delphi 7. Abia astept sa apara Delphi pe 64 bit (imi trebuie support pt mai mult de 4GB RAM). Quote foarte util ar fi daca ai putea face un mic demo din aplicatia ta care sa aibe acest behaviour. Primul lucru pe care l-as fi acut si eu ar fi fost sa sparg aplicatia in bucati mici ca sa izolez problema. Insa daca modific putin codul sursa problema dispare. La fel se intampla si daca incarc de pe disk alt set de date. Mersi pt ajutor. O sa gasesc eu cumva problema pana la urma. Am inceput sa inspectez toate unit-urile, linie cu linie, sa caut posibile erori si sa aduc imbunatatiri sau sa curat codul. Edited by dotniet, 19 July 2009 - 18:47. |
#8
Posted 19 July 2009 - 21:11
#9
Posted 20 July 2009 - 01:22
ciuly, on 19th July 2009, 21:11, said: pai si atunci de ce nu folosesti clear? Bucata aia de cod era doar pt debugging. Vroiam sa vad unde apare eroarea. Oricum s-a rezolvat. Azi am revizuit cea mai mare parte din cod, am facut chiar o mutime de schimbari si am scapat de eroare. Nu sunt sigur de unde a fost. Nu am stat sa recompilez dupa fiecare eroare. Multumesc mult pt ajutor! |
Anunturi
▶ 0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users