Chyba v Delphi?
[img]chyba7vc.png[/img]
Chcem sa spytat kedy vznikne takato chyba v Delphi? U mna sa to stalo ked som do premennej typu record pridal dalsie dve premenne rovnakeho typu (tie dve pridane su rovnakeho typu a to array[1..(X*X)-X]of Byte). Pokial som pridal iba jednu tak sa nic nestalo ale po pridani druhej sa objavila tato chyba. Stalo sa to na zaciatku podprogramu pri jeho Begin. Do premennych sa nic nevkladalo ani sa s nimi nijako nepracovalo. Nakoniec som to vyriesil zmenou tych premennych za array[1..X-1]of Byte. Z mojho laickeho pohladu to vyzera ako keby tie dve predchadzajuce struktury boli na Delphi moc velke. Aky je vas nazor?
Ano, dynamicke premenne (v procedurach apod.) sa ukladaju do zasobnika, a ten nie je nekonecny (je primarne urceny na navratove adresy fcii a predavanie parametrov).
Stack overflow znamena ze zasobnik nestaci.
//Edit: a nie je to "moc velke na Delphi", zasobnik je obmedzeny v kazdom programe, take veci sa proste nerobia.
Chcel si alokovat 2x X na druhu bytov, ak je X dost velke tak to samozrejme moze nastat. Niekde sa da v nastaveniach zvacsit velkost zasobnika, ale nauc sa na taketo veci pouzivat dynamicke pridelovanie pamate (z heap), prip. cez new objekt, apod., v tom pripade mozes alokovat tusim aj celu volnu virtualnu pamat. Pozri si nejaky tutorial o tom.
V mojom pripade X=28. Este by som chcel vediet co sa mysli "dynamicke premenne". Ja si pod tym predstavujem napr. SetLength(var S; NewLength: Integer); ktora nieje znama dopredu ale vytvori sa az pocas (pod)programu. Zmenilo by sa nieco ak by to nebolo v podprograme ale hlavnom programe?
Bol by som vdacni keby ste uviedly cast kodu ako by to vizeralo s "(z heap), prip. cez new objekt".
Dakujem
Uff sorry ale ty nemas k tomu delphi ziaden manual?
RTL.asp
Ale radsej to asi rob ako objekt, Delphi to ma nejako moc zahmlene co sa tyka pamate, nikde ziadne poriadne info, ludia maju asi radi "ciernu skrinku" ktora nieco robi a nevedia ako, ale len do doby az to zacne vypisovat stack overflow, ze
//Edit: Tu si precitaj sekciu "Variables":
http://info.borland.com/techpubs/delphi/delphi5/opl g/memory.html
Ja uz som sa tu v jednom prispevku pytal ake su limity Delphi pri praci s RAM a o ziadnom zasobniku tam nikto nic nepisal http://pc.poradna.net/question/view/34431-ake-su-hr anice-delphi. Na nieco o zasobniku si pamatam este z Pascalu ale predpokladal som ze vo Windowse uz problem s RAM nieje ako v DOSe.
Si mal spomenut ze sa pytas o obmedzeniach zasobnika, nie pamate Treba na to davat pozor, dilema zasobnik vs. heap je jedna zo zakl. veci ked ide o data.
Inac myslim ze som nasiel dynamicke pole je asi to co potrebujes, vid moj prispevok uplne dole...
P.S. zasobnik je uplne zakladna vec, pouziva ho kazdy program, nesuvisi to ani s Delphi, ani s DOSom. Aj keby si programoval v comkolvek (co vytvara aplikaciu) mal by si rovnaky problem (zasobnik vs. heap).
"Si mal spomenut ze sa pytas o obmedzeniach zasobnika, nie pamate" to som spomenut nemohol pretoze som vtedy este o zasobniku v Delphi nevedel . V tom mojom programe pracujem s poliami rangeArray : Array[1..X] of rozneCiselneTypy kde X=28; je definovane v sekcii Const v hlavnom programe. Takze pracujem iba so statickymi poliami. Vysledok je ze je to mierne predimenzovane ale pre moje uceli to tak velmi nevadi.
Dakujem za odkazi urcite si to precitam a ked nebudem niecomu rozumiet tak sa tu objavi dalsi moj prispevok na tuto temu
Tak neviem ako si takymi polom zaplnil 1MB stack.
Pouzi dynamicke pole. A pri predavani do procedury odkazom, nie hodnotou, to moze byt tvoj momentalny problem preco sa zaplnil stack.
Nevolas nejaku proceduru rekurzivne? To moze byt dalsi problem ak sa rekurzia nikdy neskonci
Tych poli je tam niekolko ci uz [1..X] alebo [1..X,1..X] a tie sa niektore skladaju este z recordov ktore obsahuju zase polia [1..X-1] popripade [1..X*X-X]. Takze ako som napisal ono sa to asi nazbiera Ta chyba ako som napisal na zaciatku vznikla pri vstupe do podprogramu kedy sa este nic neurobilo iba sa zrejme zacala rezervovat pamat pre ten zasobnik a kedze su to vsetko staticke polia tak zrejme uz vtedy zistil ze ma malo pamate (pokial to okolo toho zasobnika spravne chapem). Jedina rekurzivne volana procedura je Quicksort(A,B:Byte); takze tym to urcite nebolo.
Zasobnik je uz rezervovany, proste existuje Pri vstupe do procedury sa rezervuje miesto zo zasobnika pre lokalne premenne v procedure. Ak su moc velke tak samozrejme tam vznike problem.
Datove struktury si treba poriadne premysliet este predtym nez clovek zacne pisat program, mam pocit ze z toho mas dost gulas poli v poliach (ak som to dobre pochopil [1..X,1..X] recordov [1..X*X] tak v podstate vytvaras pole velkosti az X na stvrtu, co uz urobi aj pol megabyte pri X=28). Skus to dynamicke pole ale hlavne rozmyslaj pri tom ze co je kde v pamati ulozene aby si tam nemal milion poli zbytocnych.
Akože nikto? A čítal si čo som písal ja? Presne to isté čo teraz ty som urobil v Turbo Pascale. A od TP k Delphi to nemá ďaleko. Delphi je jeho mladší brat.
Ty si tam pisal o Turbo Pascale a Dose a kedze ja som sa pytal na Delphi a Windows tak som dospel k mylnemu nazoru ze "zasobnik bolo nieco" iba v Dose s cim sa uz vo Windovse zaoberat nemusim. Vdaka MM.. uz viem ze zasobnikom sa musim zaoberat i vo Windovse.
Do definicii delphi premennych az tak nevidim, robim v C++, vseobecne premenna moze byt naalokovana z memory heap (v C sa to vola "staticke premenne"), konstanty (naozaj nemenne, nie vsetky v sekcii "const" su nutne nemenne) mozu byt v kodovej pamati, a ostatne premenne sa alokuju zo zasobnika pocas behu programu (to som si teraz nazval "dynamicke premenne" aj ked je to dost zavadzajuce), je jedno ci to das do hlavneho programu alebo podprogramu.
Na staticku premennu zabudni ak mas velkost pola zavislu od X.
Ak je X = 28, tak si chcel naalokovat. ca 3kB. Neviem kolko nastavuje Delphi defaultne zasobnik (mohlo by to byt v nastaveniach projektu), je aj mozne ze v tej procedure alebo v hlavnom programe mas uz vela inych premennych alokovanych zo zasobnika ktore zaberaju vela miesta, alebo prenasas do procedury nejake velke pole hodnotou, ale pretecie to az na tychto 3kB.
Mam taky pocit ze objekty delphi sa alokuju z heap nie zo zasobnika, takze ak by to bol objekt malo by to byt OK, ale ako presne to mas urobit ti nepoviem, ty si Delphi programator nie ja , ja som ti len chcel napisat: Ano, mas malo zasobnika, urob to tak aby to neslo cez zasobnik.
Ak sa sem kukne Jan Fiala alebo niekto kto robi v Delphi aktivne napise ti k tomu mozno presnejsie.
Vdaka za odpoved. Este ma predsa len zaujima ak by cela ta struktura bola v hlavnom programe a nie v podprograme i tam by bol problem so zasobnikom (pokial som to spravne pochopil tak zasobnik umoznuje prenos udajov medzi podprogramami a hlavnym programom)? Je pravda ze v tom mojom programe pracujem s niekolkymi typmi zaznamov ktore su potom umiestnene v matici bud [1..X] pripadne [1..X,1..X] takze sa to zrejme nazbiera
Kukni linky co som dal vyssie.
Volaju to tam global/local premenne, nie "staticka" ako v C (co je vystiznejsie ptz. "global"/"local" suvisi s viditelnostou premennej ale to je teraz jedno).
Ak by si to urobil ako globalnu premennu tak by to neslo zo stacku, takze mozes kuknut aj na to
aa060899.htm, sekcia "unit level variables" a "global variables", ale to sa ti asi nepodari, ptz., mas velkost zavislu od momentalneho X.
Tiez davaj pozor co prenasas ako parameter do procedury, ak je tam nejake pole alebo matica tak to prenasaj odkazom nie hodnotou (snad sa to v Delphi da), to je najdolezitejsie.
Ak vytvaras velke matice tak zasadne z heap, nie zo stacku. Co vsetko ide z heap mas v tej linke co som dal vyssie (http://info.borland.com/techpubs/delphi/delphi5/opl g/memory.html), v sekcii "Variables", hlavne vetu
Long strings, wide strings, dynamic arrays, variants, and interfaces are heap-allocated, but their memory is managed automatically.
Takze ak pouzijes jeden z tych objektov (napr. dynamic array prichadza do uvahy) tak to budes mat z heap.
T.j. RTL.asp
Declaring and using dynamic arrays
Pozrel som sa do Project Options karta Linker a tam je Memory Sizes ako Min Stack Size $00004000 B a Max Stack Size $00100000 B. Takze pokial by som sa este stretol s touto chybou tak uz viem kde to mozem zmenit.
Na zaver pokial to dobre chapem tak zasobnik umoznuje prenasanie udajov medzi hlavnym programom a jeho podprogramami (procedurami a funkciami) popripade i proceduri a funkcie mozu mat vlastne proceduri a funkcie. Takze sa toto vsetko deli o zasobnik ktory ma definovanu urcitu velkost (v mojom pripade 100 000 B). Predpokladam ze by to malo fungovat tak ze pokial opustim proceduru alebo funkciu ktora mala lokalne premenne (napr. polia) tak sa zo zasobnika uvolni cast pamati ktoru zaberali?
IMHO to nie je 100000B ale hexadecimalne 100000, co je 1MB.
Ano mozes si to zvysit (pisal som ti to snad hned na zaciatku), ale nie je to rozumne (efektivita, a ak vytvaras data dynamicky tak nevies ci to pri urcitych specialnych vstupoch zas nedrbne kvoli rovnakemu problemu, apod.), pre vacsie mnozstva dat zasadne pouzivat objekty/fcie ktore pracuju s memory heap.
Ano ak opustis podprogram tak sa musi uvolnit zo zasobnika vsetko co sa na zaciatku podprogramu na zasobniku alokovalo, ptz. je nutne aby pri ukoncovani procedury bolo na vrchu zasobnika to, co pri volani procedury - navratova adresa.
Vdaka ja si tie odkazy precitam a pozrem sa ako je to tam riesene. Zatial mi staci moznost zvacsit si to rucne v tom nastaveni. Oznacil by som to za vyriesene. Ak sa stretnem z niecim comu este nebudem rozumiet tak vytvorim nove vlakno s danou temou.
Ja ešte doplním, že ak je program napísaný tak, že nekontroluje pretečenie zásobníka (čiže by ti nevypísalo túto chybu, čo si sem dal), tak to skončí spadnutím programu, pretože sa prepíše návratová adresa podprogramu. V extrémnych prípadoch sa stáva, že vďaka tejto chybe sa hacker nabúra do systému. Píšem síce, že v extrémnych prípadoch, ale tým myslím prítomnosť hackera. Ak prepíše návratovú adresu vhodnou hodnotou (vhodnou preňho), tak sa beh programu síce zrúti, ale riadenie sa korektne odovzdá systému a hacker má voľné pole pôsobnosti. Je to najčastejšia chyba v programoch, ktorá umožňuje nabúrať sytém. Takže veľký pozor na to, hlavne v programoch, ktoré bežia s najvyššími právami. Ak sa nemýlim, dokonca niektoré vírusy takto odpravia do večných lovísť mnohé z antivírov (niekde som to tuším čítal).
Takže ako má Intex vo svojom podpise na živě:
To mas pravdu, bohuzel je to tak, mne zase vic stve ze nove delphi maj udelanou tak blbe napovedu (plovouci), pri prejezdu mysi jakekoliv procedury nebo funkce skoci napoveda ale nez najede je to treba 2-3 sekundy, tak se to jakoby zasekne , tak sem to vypnul a mam pokoj.
Nemas pravdu. To co popisujes nie je problem nedostatku zasobnika, to co popisujes je zneuzitie chyby programatora ak si nekontroluje velkost vstupu (v pascale by sa to nemalo stavat ptz. pascal interne kontroluje pristupy do pola).
priklad (C/C++):
void SpracujSlovo(char* slovo)
{
char pomocnybuffer[20];
strcpy(pomocnybuffer, slovo); - tu je bezpecnostna diera, hacker ju moze zneuzit ak vie sposobit ze "slovo" bude mat viac ako 20znakov
...
}
Nema to nic spolocne s velkostou zasobnika, ten moze byt aj milion gigabytov stale to bude derave.
Ak by bol maly zasobnik a nekontrolovalo by sa to, tak by si sa dockal pravdepodobne windows hlasky "program proved nelpatnou operaci a bude ukoncen" ptz. by sa prekrocil limit stack segmentu (CPU exception).
Mal som na mysli chybu programátora, vďaka ktorej vypíše Delphi chybu, ktorú sem dal Andrej.
To spolu nesuvisi!
Pri chybe o ktorej pises sa nevypise chybove hlasenie "stack overflow". Proste pises o niecom inom. Andrej len pouziva prilis vela velkych lokalnych premennych, to nie je bezpecnostna diera, (neda sa to zneuzit hackerom), je to len problem v tom ze mu nastavena velkost stacku nestaci a program je v tom momente preruseny.