» Poradna » Programy

C/C++ dynamická alokace paměti

 |   |  Linux Firefox 78.0

Zdravím,potřeboval bych od Vás trochu objasnit problematiku týkající se dynamického (rostoucího) pole a s tím související dynamickou alokaci paměti - malloc, realloc, případně new v C++ apod. Jde o to, že ve všech návodech, videích apod je ten postup prakticky totožný ->1. vytvořím si pole na haldě o nějaké velikosti např. int* heapArray = (int*) malloc(3 sizeof(*heapArray));2. poté, až kapacita tohoto pole nebude dostačovat, tak se použije realloc (data zůstanou, velikost pole se zvětší - většinou např. 2x)3. v C++ jelikož realloc není, tak se to buď řeší buď přímo zabudovaným vectorem a nebo vytvořením druhého většího pole a zkopírováním hodnot z prvního do tohoto nově vytvořeného pole.4. to vše samozřejmě ideálně zakomponovat do nějaké struktury která bude obsahovat další proměnné, jako kapacita, velikost apod...Dynamické pole jsem podle kódů z návodů pochopil, ale trochu jsem si s tím hrál a vůbec jsem nepobral pár věcí. Na tyto věci (celkově 2) se ptám přímo v komentářích v první části kódu kódu - příšlo mi to přehlednější, než to vypisovat sem.první a druhá část je oddělena hvězdičkamiv druhé části jsem se bez nutnosti používat realloc nebo vytvoření druhého pole snažil vytvořit primitivní dynamicky rostoucí pole a zdá se, že vše funguje (žádný problém jsem nezaznamenal).https://pastebin.com/AjnceehBJelikož jsem na internetu nic podobného nenašel, tak jsem se rozhodl zeptat se zde vás.Buď to funguje, protože to prostě fungovat může a není to spatně, a nebo je to totálně celé špatně, ale funguje to (vím, že tohle se u C/C++ stát může) :D.Děkuji za odpovědi.//Zkráceno přehlednějším odkazem s formátováním.//

Mohlo by vás také zajímat

Odpovědi na otázku

 |   |  Microsoft Windows 10 Firefox 78.0

Proč být nějaký troškař a alokovat pole na hnoji (stacku) po troškách, když můžeš přímo alokovat potřebnou velikost RAM a s daty pracovat přímo v ní .Příklad alokace 5GB RAM (pro načtení dat ve velkém souboru, čtení po 2 501 566 399 bytech najednou a práci s načtenými daty v RAM).//* Alokujeme pamět pro celý soubor *// static const SIZE_T giga = 1024 * 1024 * 1024; static const SIZE_T size = 5 * giga; ptr = static_cast<BYTE*>(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); bsrc = ptr;

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 10 Firefox 78.0
 |   |  Microsoft Windows 10 Chrome 83.0.4103.116

heapArray máš alokovaný iba pre jeden int. Všetky priradenia do heapArray[x], kde x je väčšie ako 0 ti prepisujú haldu v tebou nealokovonom mieste...

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Microsoft Windows 10 Chrome 81.0.4044.138

Nejprve par poznamek:2. realloc() muze zachovat data, ale take muze vytvorit novy blok, kam ta data zkopiruje. V tu chvili pripadne existujici ukazatele nemaji platnou hodnotu.3. v C++ realloc() je samozrejme take, ale ve vetsine pripadu neni potreba.Obecne je dobre realloc() nepouzivat, neni-li to nutne, protoze neni zarucene zda se operace podari, nelze predem poznat, zda se bude vytvaret novy blok pameti a data kopirovat, coz neni efektivni.A ted odpoved na otazky: ano, je to totalne cele spatne, ale funguje to diky nahode :)Ta pamet, kam se zapisuje za hranici alokovaneho pole tam muze, ale take nemusi byt (segmenty pameti lze omezit na urcitou velikost, nebo tam nemusi byt namapovana fyzicka pamet, atd.), to zalezi na operacnim systemu. A i kdyz tam ta pamet je, muze patrit jinemu objektu a timto se tam zanesou paradni chyby.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Linux Chrome 84.0.4147.89

Pak je taky často k vidění použití "ptr = realloc(ptr); if (!ptr) { goto chyba; }", co při chybě leakuje paměť, protože realloc nechá původní data alokovaná i když vrátí NULL.V C++ je v 99% případů lepší používat STL.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Linux Chrome 84.0.4147.89

A ještě jsem zapomněl na AddressSanitizer, ten je při ruční správě paměti v podstatě nezbytnost.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Chrome 84.0.4147.89

u dynamických polí je třeba brát v úvahu jisté zákonitosti.problémem tvého příkladu je, že pokud tam nedáš počet, tak alokuješ paměť jen určité velikosti a můžeš se dostat mimo oblast přidělenou programu, případně může dojít ke kolizi s jinou oblastí, kdy změnou údajů v jednom dynamickém poli dojde ke změně údajů jiného dynamického pole nebo proměnných.Správný Debuger ti pak při testování rovnou řekne, že se pokoušíš pracovat s nepřidělenou pamětí.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Chrome 84.0.4147.89
 |   |  Microsoft Windows 10 Chrome 84.0.4147.89

Tam je pěkně mrtvo.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 10 Chrome 84.0.4147.89

silne doporucujem nepouzivat vlastne postupy pre dynamicke polia a vytvorit si jedno, dostatocne velke. v opacnom pripade pouzivat iba pomalsi ale istejsi vector.takmer vsetky hry na sposob minecraftu, ktore pouzivaju velke polia s dynamickymi zmenami, maju toto ako hlavny zdroj chyb, bez moznosti ich ovplivnit.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Microsoft Windows 10 Chrome 83.0.4103.119

Velikost polí musíš udávat! Minimálně z důvodu aby bylo jasné, co je ještě volné, a tedy kde se může paměť alokovat pro další dynamicky alokované proměnné.Tvůj příklad funguje, ale jen díky tomu že v něm nemáš nic jiného a díky tomu jak systém přiděluje paměť procesům.Schválně si vyzkoušej vytvořit dvě pole. Jedno třeba na 3 prvky a druhé na 5 prvků.int* heapArray3 = (int*) malloc(3* sizeof(int));int* heapArray5 = (int*) malloc(5* sizeof(int));Pak to naplň daty:heapArray3[0] = 300;heapArray3[1] = 301;heapArray3[2] = 302;heapArray5[0] = 500;heapArray5[1] = 501;heapArray5[2] = 502;heapArray5[3] = 503;heapArray5[4] = 504;A teď si zkus vypsat prvních 5 prvků z pole heapArray3. Nejspíš to vypíše hodnoty: 300, 301, 302, 500, 501. A zkus hádat proč.A jako bonus si zkus vypsat Milióntý prvek pole heapArray3 a hádej proč to crashne. heapArray3[1000000]

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Linux Chrome 84.0.4147.89

Tak tady máš pár příkladů: https://pastebin.com/aYpQYH6PNaprosto zjevný memory leak: nikde neuvolňuješ heapArray. Použij raději C++ a (a) alokaci na zásobníku pro malá pole nebo (b) std::unique_ptr, abys na dealokaci nemusel explicitně dbát.Zkoušel jsi to spustit s valgrindem? Zjevně ne, protože jinak by bylo jasné, že když si naalokuješ "pole" o velikosti jednoho intu (4 byty), tak potom zápis do položky 0 sice dává smysl, ale zápisy do položek 1 a 2 dělají něco nedefinovaného. Tedy zapisují náhodně do paměti, někam kdovíkam, za konec toho 4-bytového (1-intového) pole. Tam může být cokoliv. Třeba struktury alokátoru paměti. Který pak při dalším pokusu o alokaci / dealokaci odletí. Doporučuji víc než vřele valgrind.Komentář "v pořádku" je fakt vtipný. Ne, zapsat něco náhodně někam do paměti, která není řádně alokovaná, opravdu ale opravdu není v pořádku.> jakou hodnotu má dalších 7 políček a existují vůbec?Nikde neexistují žádná políčka. Existují jenom pointery a adresy ve virtuální paměti. Můžeš se pokusit zapsat kamkoliv nebo přečíst cokoliv. Když bude mít proces zrovna náhodou příslušnou stránku namapovanou (mmap binárek a knihoven, předalokovaná halda, rezerva pro zásobník, kdesicosi), bude to zdánlivě fungovat a něco jakože dělat. Pokud ovšem ta pamět (příslušná stránka) nebude namapovaná, celý proces samozřejmě (po zásluze!) odletí. (Pokud tedy nemaskuje SIGSEGV a nechce takový stav nějak sám ošetřit. To nikdo kromě debuggeru nebo JVM asi nechce.) Pokud paměť (příslušná stránka) bude namapovaná, hodnota záleží na tom, co ji zrovna používá. Pokud nic, budou tam prostě náhodná data, která tam jen tak zbyla po předchozím použití. Dost často to můžou být samé nuly, jindy zase něco jiného. Náhoda.Datové struktury jsou abstrakce nad lineárně adresovanou pamětí. Samy od sebe neexistují. Existují jen v představách programátora a Ukázat celý příspěvek

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Linux Firefox 78.0

Děkuji všem za velmi poučné rady, které pomohly! :) nechtěl jsem se vrhat do něčeho dalšího, dokud aspoň částečně nepochopím tohle. Teď se můžu pustit do dalších pokusů.

Souhlasím  |  Nesouhlasím  |  Odpovědět

Související témata: Pole, Alokace, Druhá část