
Rychlá pomoc s programem (Delphi7)
Ahoj,
z časových důvodů potřebuji někoho, kdo mi pomůže s jednou mou aplikací v Delphi. Je to jednoduché demo předvádějící grafické transformace.
Problém asi s dědičností (Canvas-Bod-Primka...), kdy se mi pak některé prvky snaží uvolňovat 2x a celý program je nestabilní a neustále vyhazuje AV (při ukončení).
Nemůžu na to přijít proč a jak to navrhnout správně, tak chci zkusit druhé oči.
Potřebuji testovat vlastní kreslící algoritmy, to ale nemůžu, když mám špatně navržený základ. V delphi už dělám spíš příležitostně, tak mi to moc nejde.
Odměna dohodou, spěchá.
Když nemůžeš najít proč se to uvolňuje dvakrát, tak jednoduchá finta (ale není to elegantní řešení, leč funguje):
nebo já používám na to proceduru:
Pro přesnější radu bych musel program vidět. Nemusí (jak se mi zdá) jít o problém dědičnosti, ale zapouzdřenosti (to je rozdíl!) Kontejnerový objekt by měl sám uvolnit uvnitř přidané objekty, ale musí je znát, proto zadáváme do konstruktoru objekt majitele (obvykle parametr AOwner). Konstruktor pak zajistí, aby kontejnerový objekt (třeba formulář) sám uvolnil vnořené objekty (tlačítka, canvas, textová pole....).
Takto to mám, ale problém to neřeší.
Podle mého jde o to, že na formu mám image, a pak mám vlastní třídu BaseCanvas, která má privátní proměnnou Image (nastavuji konstruktorem).
No a co jsem se pokoušel to trasovat, tak při destroy BaseCanvas se Image uvolní, a pak při destroy formu se ho snaží zrušit znovu.
Snažil jsem se různě přepisovat destruktory (override bez inherited), ale bez výsledku. Možná je ale potíž úplně v něčem jiném... :(
Můžeš mi když tak, prosím, napsat kontakt na cizek.milan@seznam.cz, zdrojáky poskytnu.
Skype/Jabber také můj mail.
To ne přepisovat destruktory je cesta do pekla. Máš nějaký binec v ownerech přidávaných objektů. Jestli je přidáváš v IDE rovnou taháním myši na form, nestarej se o nic, form to uvolní sám v pohodě. Jestli to přidáváš dynamicky, tak musíš volat správné metody aby se to správně propojilo, teď to nemám delphi před sebou, abych ti to správně řekl (používám free Lazarus).
Jo je to jeden form s image ale všechny mé vlastní třídy pak vytvářím dynamicky.
Jinak používám jen čisté VCL, tak by to mohlo jít i v tom Lazarusu?
Určitě. Dělám s tím programy pro Linux úplně bááááječně, pro Widle taky. Jestli to přidáváš dynamicky, měl bys použít metodu AddObject kontejneru, do kterého to cpeš. Pak by to mělo uvolňovat samo.
Můžeš mi poslat zdroják na rce(zavináč)arkotechnik(tečka)cz a můžu se na to zkusit mrknout, mám ještě někde Delphi 7. Jsem teď ale dost vytížen, tak neslibuju, jestli se k tomu rychle dostanu.
//edit: V podstatě podobného něco jsem dělal, program na editaci obrázků, kde jsem náhledy (TImage) dynamicky cpal do mřížky. Funguje to dobře, s uvolňováním nemám problémy.
Ta tva trida urcite neuvolnuje predany Image automaticky, to musis uvolnovat nekde ty v destroy sveho objektu.
Formular je vlastnikem Image, takze bys mel nechat jeho uvolneni na formulari.
Urob to v C(prip. aj ++ ak chces) a nebudes mat taketo problemy.
To je rada jak cyp...
Fungovat to musi v jakemkoliv jazyce, kdyz to bude napsane spravne...
No ale evidentne to napsat spravne nevie.
Delphi a podobne kde si predavas hore dole objekty vytvorene vo vnutrach funkciie, tam sa to oesefovava potom dost blbo. V C presne vies co si kde vytvoril a co kde mas, ptz sa nic nerobi samo.
V Delphi se taky nic nedela "samo". Není tam zadne automaticke uvolnovani, jako v C#, zadne garbage collectory.
Je na tobe, abys to napsal v poradku.
V C++ si taky predavas ukazatele na objekty. Pokud si predas ukazatel, na jinem miste ten objekt uvolnis a budes se k nemu snazit pristupovat, dopadnes stejne - access violation.
TCanvas (platno) je jen objekt, ktery umoznuje vykreslovani. Pokud bys to delal v C++, budes neco takoveho potrebovat taky, pokud to budes chtit vizualizovat.
Tak to budes, ale osefujes si to vsetko sam ptz si to musis vsetko urobit sam :)
BTW. k tomu dotazu - ked mu canvas chce pristupovat na objekt ktory uvolnil predtym, tak nech hlada problem tam, a osefuje si pristup na objekt ked uz neexistuje nejakym if, alebo nech ten objekt vyhodi z canvasu prec.
V Delphi si delas taky vse sam - vytvaris, rusis. Funguje to stejne jako C++.
Neni to zadny semi language jako C#, je to cisty objektovy jazyk.
A rozlisujes aj medzi tym ze co je len pointer a co je skutocny objekt? ;)
(IMHO to je to co moze zaciatocnikov miast, a v C++ je to jasne a striktne odlisene)
Tim, ze priradis objekt do jineho, tak predas ukazatel na objekt, ale pak pracujes primo s vlastnostmi objektu.
V podate prace s objekty v Delphi (tecka) odpovida praci v C++ (pomlcka+sipka)
Delphi: myclass.DoSomething();
C++: myclass->DoSomething();
Kdyz takto nekde v C++ predas objekt do nejake metody jako parametr a uvnitr metody jej zrusis, tak jsi zrusil objekt. Stejne jako V Delphi.
Muzes pracovat i primo s obecnym pointerem, pak kdyz se chces dostat na vlastnosti, tak si musis ponter pretypovat na ten objekt. Tohle se moc nepouziva, protoze neni duvod a stezuje to citelnost kodu.
priklad:
class Cosi
{
public:
Neco neco; // staticke, vytvorenie aj delete mi osefuje konstruktor a destruktor triedy Cosi.
Neco *neco = NULL; // pointer na nejake moje dynamicky vytvarane neco, a nikto sa mi do toho nesere. Sam si musim osetrovat pristpy a nepristupovat ak to je NULL, a nastavovat na NULL ak objekt deletnem.
}
Tohle funguje stejne a chova se to stejne.
Co si takto dynamicky vytvoris, tak si to musis sam i zrusit v destroy objektu. Nic se ti automaticky nezrusi.
Cosi = TClass
public
Neco1: integer;
Neco2: TPointer;
end;
Ja si myslim ze je to matuce, minimalne to oznacovanie (prve je objekt, a vyssie pises ze to je furt len pointer). V C to jasne vidis ze co mas, tym padom vies co s tym mozes robit a co ne.
Mozno mu ta diskusia pomoze prist na chybu
To NEco1 je uz vytvorene automaticky? Ak ano tak co sa stane ked napise
Neco1 = new integer
?
a potom delete Neco1
a destruktor potom sa snazi uvolnit znova co je samozrejme blbost, ptz je v tom maglajz ze co je pointer a co je uz vytvoreny objekt (?). Len filozofujem ale moze to byt prave jeho problem.
Pointery se normalne v objektu nepouzivaji, protoze neni duvod.
To neco1 je staticke - treba metoda objektu, to neco2 je jen odkaz na objekt.
Neco1 muze byt i odkaz na jiny objekt
Realny priklad:
Read a write mohou byt i metody, ve kterych budes delat i neco jineho nez prirazeni do vnitrni promenne.
At provedes nekde prirazeni
Pri ruseni objektu se ti prirazeny objekt sam nerusi, pokud to neudelas ty sam vedome kodem v destruktoru objektu. A je jedno, jestli si ho priradis takto nebo jako parametr v metode Create objektu. Predane objekty odkazem se samy nerusi.
Presne o tom pisem ze z toho tvojho zapisu neni jasne ci je v pamati cely objekt alebo ne.
promennaObrazek: TImage;
v pamati je teda alokovane co?
MujObjekt.PromennaObrazek := Form1.Image1;
v pamati je teda teraz alokovane co?
Ked zrusim Form1.Image1 tak ostane v pamati PromennaObrazek alokovane co?
V Delphi to programator nevidi = bordel. V C to jasne vidis ze co je fyzicky vytvorene v pamati. Bud pointer alebo objekt.
Oba zapisu jsou totozne a odkazuji se na objekt Form1.Imagex (je to jen forma pointeru). Nealokujes zadnou "kopii" objektu
Pokud zrusis Form1.Image1, tak v obou pripadech zustane v promenne i property odkaz na puvodni obrazek - bude odkazovat na neexistujici objekt.
V Delphi muzu udelat:
Pokud to udelam takto, v te chvili jsem ztratil moznost se dostat k objektu, ktery jsem v prvnim radku vytvoril. Ale podobne dopadnu i v C, pokud dam new obrazek a pak to prepisu odkazem na nejaky existujici objekt. A pokud ten objekt z vnejsku zrusim, tak i C ti bude ukazovat na neexsitujici objekt.
V C si to mozes osefovat sam ze ci si skopirujes objekt, alebo len priradis pointer
Taky si muzu zkopirovat objekt, treba:
mujobrazek.assign(form1.image);
pak mam v promenne mujobrazek kopii objektu. Ale pouziti tohohle nebo objektu zalezi na konkretnim vyuziti. Vetsinou pracuju s odkazem a nepotrbeuju kopirovat objekt.
Ale ten zapis je matuci.
Neco integer
Neco := 1 kopirujes hodnotu
Neco neviemco
Neco := necoine zasa kopiruje pointer
je v tom gulas, to pisem od zaciatku :) Gulas => programtor je zmeteny => chyby :)
P.S> mne je jasne ze budes Delphi obhajovat, ale nemusis ma presviedcat, ja som v tomto nepresvedcitelny
Tak jsem ti něco poslal...