Malá poznámka: Místo malloc pro alokaci pole jde v C3 použít mem::new_array například int[] a = mem::new_array(int, SIZE); ( mem::new_array vynuluje pamět, krom něj existuje mem::alloc_array, který neneuluje). Přiřazení do slicu (místo ukazatele) zajistí, že se při indexování kontroluje indexace mimo pole, takže kód je bezpečnější.
U literálů přiřazovaných do ZString není třeba psát \0 explicitně. Stačí ZString s = "Hello world!";
takze vlastne rezy jsou zde skutecne "jen" pohled na pole, nebo muzeme delat i "append" tak, jako v Gocku? (je to IMHO jedna z dobrych vlastnosti Gocka, spolecne s defer + konkurenci)
To append predpoklada, ze interne bude nekdo/neco realokovat pole, ale IMHO to nevyzaduje zadny GC. Ci?
> takze vlastne rezy jsou zde skutecne "jen" pohled na pole, nebo muzeme delat i "append" tak, jako v Gocku? (je to IMHO jedna z dobrych vlastnosti Gocka, spolecne s defer + konkurenci)
Ano, na pole nebo na nejaky souvisly kus pameti.
> To append predpoklada, ze interne bude nekdo/neco realokovat pole, ale IMHO to nevyzaduje zadny GC. Ci?
V C3 se bezne pouziva nekolik ruznych alokatoru zaroven. Takze to, co rikate, by teoreticky slo, kdyby kompilator umel zjistit, jaky alokator se ma pouzit.
> To append predpoklada, ze interne bude nekdo/neco realokovat pole, ale IMHO to nevyzaduje zadny GC. Ci?
Právě že se to bez GC komplikuje. Problém je vlastnictví paměti.
V Go veškerou paměť vlastní Runtime/GC. Takže řezy můžou předchozí paměť zahodit bez ohledu na to odkud je. Z pohledu sémantiky kódu se vlastně žádné uvolňování paměti ani neděje. Je to jen implementační detail uvnitř runtime.
Ve chvíli kdy je uvolňování paměti součást sémantiky kódu, tak se komplet mění situace. Najednou je třeba řešit, kdo tu paměť vlastní a je zodpovědný za její úklid. Takže ten řez by musel začít řešit, jak se zbavit toho starého bloku paměti.
Konfigurovat ten řez (třeba skrz nějakou dependency injection) je opruz. Bez GC je praktičtější rozlišovat jen pohled + vlastnící kontejner. Třeba jako span + vector v c++.
no v Go můžu získat ukazatel na prvek z řezu (tedy z toho pole pod řezem), potom už je vlastnictví diskutabilní. Vlastně - to jsem ani nezkoušel, musím otestovat, jak si s tím Go poradí (jedna z možností: asi zůstane původní pole v paměti)
Neřekl bych, že je vlastnictví diskutabilní. Z pohledu kódu tam nemá o vlastnictví té paměti moc smysl mluvit. Co se jednou alokuje zůstane alokované navždy. GC smí uklízet (a alokovat na stacku a podobně) jen, když má jistotu, že ho při tom nechytí.
Má smysl přemýšlet leda tak o vlastnictví objektů v té paměti. V tom smyslu že realokací toho řezu přijdu o přístup k těm starým objektům. Že ty úpravy před realokací mohl vidět i někdo jiný.
já to myslel tak, že se nedá vždycky říct "pod slicem je sice pole, ale to vlastní ten slice a tudíž dochází při přidávání k realokacím", protože i jeden ukazatel držený v nějaké další proměnné nebo parametru ty realokace nedovolí (bude to plnohodnotná alokace). Ale asi si rozumáme
24. 9. 2025, 12:47 editováno autorem komentáře
proto se priznam, ze mam rad jenom pointery v c, kde se jednou musi naalokovat a na jednom miste se musi uvolnit, vytvari to mnoho problemu, ale vlastne je to jednoduche, sahat na to muze kdokoliv, pointer v c je takova lehka i kdyz vlastne tezka holka. ale kdo to naalokoval by to mel uvolnit.
reference v c++, rustu a jinych jazycich nemam vubec rad protoze to jsou opravdu lehke holky co nic nevlastni.
i kdyz me to uvnitr trochu stve, tak golang to vyresil dobre, kazdy muze mit pointer jako lehkou holku, ale tu stejne zavede do stada zpet pasak garbage collectoru.
mozna by mohl fungovat nejaky defer, tam kde se pamet s pointerem naalokuje, tam se taky udela defer a ten by snad mohl ohlidat i uvolneni.
"mozna by mohl fungovat nejaky defer, tam kde se pamet s pointerem naalokuje, tam se taky udela defer a ten by snad mohl ohlidat i uvolneni."
Tohle by měla řešit escape analýza, ne? Na rozdíl od Javy, kde všechno je na heapu, tak v golangu se na heap dává opravdu jen to co je nutný.
> Tohle by měla řešit escape analýza, ne?
Jo a ne. Escape analýza potřebuje záruku, že si nikdo volaný ten pointer neuloží. Takže buď musí vidět dovnitř všeho, nebo mít nějaký druh anotace pro pointery které nepřežijí návrat z volané funkce.
V jednoduchém jazyce, co nemá děsivě komplikovaný arzenál pointerů, je escape analýza kastrovaný mrzák. A dává smysl jen jako optimalizace toho, když ten jazyk nemá lokální proměnné a všechno se musí dělat na heapu.
No nevím. Pointer v C může ukazovat jak něco co vlastním a musím uvolnit tak i na něco co nevlastním. Rozdíl si musím pamatovat, z toho pointeru to nepoznám. Reference v C++ jsou v tomhle úplně stejné. Že je všichni používají jen na věci, co nevlastní, je vlastně jenom zvyklost. Jazyk to nijak nehlídá.
Ale je to zvyklost IMO velice rozumná. Používat jeden druh pointerů na dvě odlišné věci je náchylné k chybám. Ve chvíli kdy mám různé druhy pointerů na něco co vlastním a něco co nevlastním, tak už je to jen krok od toho, aby se o to uvolňování mohl postarat sám ten pointer.
Bohužel i Golang a spol. musí řešit vlastnictví. Protože paměť není ani zdaleka jediný zdroj, který je nutné uvolňovat. Jazyky bez GC obvykle všechno uvolňování řeší jedním společným mechanismem. Nechat líný GC uzavírat soubory a sockety obvykle nedopadne moc dobře.
no Gocko vlastnictvi resit musi, ale a to GC, takze to neni takova zlost, jako kdyby si to musel nejak resit devel (bud s pomoci, jako ma Rust, nebo proste nejak ve vlastni rezii jako to "umi" cecka)