.[ ČeskéHry.cz ].
Vyjimky (Exceptions) v hernim prumyslu
Jdi na stránku Předchozí  1, 2, 3, 4, 5  Další
 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
pcmaster



Založen: 28. 07. 2007
Příspěvky: 1821

PříspěvekZaslal: 24. červen 2013, 15:45:19    Předmět: Odpovědět s citátem

Ak ide o tento konkretny priklad, tak je to jedno. Ale predstav si namiesto "int" vlastnu triedu a v prvom pripade dojde ku kopirovaniu, co moze byt uplne katastrofalne.
Tak ci onak, ten prvy priklad je napicu a z najroznejsich dovodov by mali byt tie parametre opatrene aspon const.
_________________
Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
rezna



Založen: 27. 07. 2007
Příspěvky: 2156

PříspěvekZaslal: 24. červen 2013, 20:54:15    Předmět: Odpovědět s citátem

pcmaster napsal:
Ak ide o tento konkretny priklad, tak je to jedno. Ale predstav si namiesto "int" vlastnu triedu a v prvom pripade dojde ku kopirovaniu, co moze byt uplne katastrofalne.
Tak ci onak, ten prvy priklad je napicu a z najroznejsich dovodov by mali byt tie parametre opatrene aspon const.


samozrejme ze kdyz tam je vlastni trida, ziskava to uplne jine rozmery apod.

ale Lemik to tu prave "rozhicoval" s intem a tak cekam jak to obhaji

jinak int a a const int a vyjde na stejno IMHO
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
VladR



Založen: 30. 07. 2007
Příspěvky: 1322
Bydliště: Greater New York City Area

PříspěvekZaslal: 24. červen 2013, 21:42:46    Předmět: Odpovědět s citátem

Neviem kolko z vas pouzili exceptions v hlavnej renderovacej smycke, ale ja to mam v svojom C++ engine uz asi tak 8 rokov (a vtedy som kodil na hodne pomalej sunke) a nikdy som nezaregistroval pokles vykonu, dokonca ani pri terene, co renderoval v 3000 FPS.
A to tam nemam try/catch jeden ale tak zo 10 ich tam bude.

Niekolkokrat som si overil v release builde, ze vyremovanie exceptions neprida ani jeden jediny frame na vykone, takze ich nechavam zapnute cely cas pocas vyvoja, lebo uzasne ulahcuju debugovanie.

Teda, aspon ulahcovali, do doby nez som sa naucil pred ~8 rokmi pouzivat pointery spravne. Odvtedy sa pustili len zriedka, resp. ked som namiesto refaktoringu robil refucktoring (vtedy su fakt na nezaplatenie !)

Potom som presiel na C# / XNA a tam exceptions pre zmenu netreba fragmentovat vobec - pretoze staci jeden jediny try/catch na celu hru v hlavnej smycke v Program.cs a ten pekne vyhodi stacktrace, hoc aj 15 urovni dozadu, ze kde presne, na ktorom riadku a preco sa vynimka vyhodila).
Tento system nechavam aj v release builde, pretoze ked sa nieco poserie, tak netreba ziadne logy a podobne hovadiny. User proste postne screenshot a hned presne viem, co kde a preco sa posralo...

Bez exceptions ani ranu Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Lemik



Založen: 30. 07. 2007
Příspěvky: 138

PříspěvekZaslal: 25. červen 2013, 04:47:38    Předmět: Odpovědět s citátem

mar napsal:
Lemik napsal:
int add ( int value1, int value 2 )
namísto
int add( const int& value1, const int& value2 )
(a to dokonce i v knize o algoritmech...)

Tak tohle není zrovna dobrý příklad. Elementární datové typy, co se vejdou do registru, nemá smysl předávat referencemi (pokud nejsou výstupní) - co je jednodušší, sečíst dvě hodnoty nebo dereferencovat dva ukazatele a sečíst výsledek? Samozřejmě za předpokladu, že to překladač nezoptimalizuje. U objektů je situace jiná, pointa byla vyhnout se kopírování objektů.
rezna napsal:
pcmaster napsal:
Ak ide o tento konkretny priklad, tak je to jedno. Ale predstav si namiesto "int" vlastnu triedu a v prvom pripade dojde ku kopirovaniu, co moze byt uplne katastrofalne.
Tak ci onak, ten prvy priklad je napicu a z najroznejsich dovodov by mali byt tie parametre opatrene aspon const.


samozrejme ze kdyz tam je vlastni trida, ziskava to uplne jine rozmery apod.

ale Lemik to tu prave "rozhicoval" s intem a tak cekam jak to obhaji

jinak int a a const int a vyjde na stejno IMHO


Neobhájím. Spadám přesně do toho případu špatné výuky.
(Mohl bych ale takový příklad napsat, vysvětlit proč ho píšu takto a zmínit se proč to není moc vhodné.)

Předně - opravdu věřím, že rozhodnutí o tom jak s kódem naložit, mám přenechat překladači. Ví toho mnohem víc než já, psali ho lidi mnohem chytřejší a nadanější než já. Alespoň bych si tak měl přečíst manuál k překladači. A navíc překladače se stále vyvíjí, kdežto ten kód co napíši už s největší pravděpodobností přepisovat nebudu.



Co tedy int add( const int& value1, const int& value2 ) říká?
- že jsem nad příkladem moc nepřemýšlel
- hodnotu se snažím předat pomocí reference - nechci vytvořit v paměti místo, kam bych hodnotu zkopíroval, a používal ve funkci tuto novou hodnotu - dávám přednost používat hodnotu původní (a potenciálně jí i měnit)
- const říká, že ale tu hodnotu NESMÍM ve funkci změnit - a překladač to má (při překladu) ohlídat.

Mám rád pohled, kdy funkce je jako uživatel, kterému dám k dispozici pár hodnot jako parametry, ať si s nimi dělá co chce. Přitom mu určím podmínky:
- předávám Ti parametr(existující proměnnou) hodnotou = Dělej si s hodnotou co chceš... Nezáleží mi na tom, co s ní uděláš... Radši bych tě ani neměl nechat si hrát s původní hodnotou.
- předávám referencí = Dělej si s hodnotou co chceš, ale jsem zvědavý a předpokládám, že tu hodnotu změníš - a později si ji přečtu.
- předávám jako const = Můžeš číst, ale nechci, aby jsi jí měnil, sorry... U předání hodnotou to trošku ztrácí smysl (ale být C++ const by default, tak se o tom ani nebavíme)
- předání pointerem = Tady máš "černou díru", dělej si s ní co chceš... Já těď poběžím třeba tímhle směrem, no a kdyby něco, bylo mi ctí... A teď vážně: měl by jsi si zjistit, jestli ta adresa existuje (nullptr), pokud z ní hodláš číst (rozdíl oproti referenci, tam ti říkám, že ta adresa existuje).
-> Jestli chci, aby jsi ji vytvořil, že na ní někdy kouknu? Eeem... To bych asi chtěl, kdybych to dal jako návratovou hodnotu, ne jako parametr...
-> Jestli jí máš smazat? (zamyslí se nad int const* value) Eeem, proč Tě to tak moc vlastně zajímá? (pro jistotu se zamyslí nad const int* const value, nebo unique_ptr/shared_ptr)



Takže, když to shrnu, jde mi o to co tím kódem říkám. V C++ mám tuto možnost, takže když můžu, rád ji použiji - a spíše pro toho, co kód bude číst a možná používat, než kvůli kompileru.

Samozřejmě, že int a const int je v podstatě to samé (z hlediska toho, co chceš a co by překladač měl udělat), jde spíše o princip nebo o zvyk psaní. Pro člověka to může mít význam (třeba i ten, že chtěl napsat const int& a zapomněl, tak si toho jednou možná všimne, anebo ten co přijde po něm to napraví), pro překladač v tom rozdíl není.

const int& - někdo se usměje, co je to za blbost, kompiler prostě použije původní hodnotu a tuším ani neřeší že se jedná o referenci, což by řešil v případě ne-const reference, a někdo koukne a pochopí, že nejde o idiom "čekám, že tuto hodnotu změníš".

- Ano, používat unique_ptr kvůli int* je blbost. Kdo to udělá, je asi až trošku moc nejistý, cvok nebo tomu totálně nerozumí. Pointery bych rozhodně nezmiňoval pro začátečníky - reference by měli znát mnohem dříve než pointery - opět by to byl špatný příklad, ale chtěl jsem vysvětlit ten pohled.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Weny Sky



Založen: 28. 07. 2007
Příspěvky: 241

PříspěvekZaslal: 25. červen 2013, 08:15:27    Předmět: Odpovědět s citátem

Lemik napsal:
předání pointerem = Tady máš "černou díru", dělej si s ní co chceš... Já těď poběžím třeba tímhle směrem, no a kdyby něco, bylo mi ctí... A teď vážně: měl by jsi si zjistit, jestli ta adresa existuje (nullptr), pokud z ní hodláš číst (rozdíl oproti referenci, tam ti říkám, že ta adresa existuje)

Obavam se, ze referenci mu predas NULL uplne setejne jako pres pointer. Vem si situaci, kdy predavas do funkce nejaky objekt, a predavas zrovna prvni objekt z dynamicky alokovaneho pole, ktere si ale zapomel alokovat :
kód:
int *arr = 0;
add(arr[0], arr[1]);
Nehleda na to, ze pri pouziti pointeru nemusis vubec testovat jestli je NULL, protoze je to zbytecne. Kdyz to tam nekdo preda, tak to proste spadne a je to jeho problem. Max si v debug modu hlidat vstupni parametry assertama, ale tahat takovy balast do releasu. No nevim nevim.

Dalsim problemem u te funkce add je, ze kdyz budu chtit jako parametr predat vyraz, tak se zbytecne vytvori nejaka docasna promenna viz nasledujici kod:
kód:
int xyz = 10;
int zyx = 11;
add(zyx + xyz, zyx + 20);


A s takovyma vecma ti vetsinou nepomuze ani optimalizer. Proste si to tak chtel, tak to tak mas. A ve vysledku budes mit nejpis pomalejsi kod. A kdyz ti to zoptimalizuje, tak do pouziti int add(int a, int b), takze je nesmysl neco takoveho pouzivat a spolehat na prekladac, kdyz je to od pohledu spatne Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
OndraSej



Založen: 28. 07. 2007
Příspěvky: 765
Bydliště: Brandýs nad Labem

PříspěvekZaslal: 25. červen 2013, 09:03:27    Předmět: Odpovědět s citátem

Lemik napsal:
Co tedy int add( const int& value1, const int& value2 ) říká?
- že jsem nad příkladem moc nepřemýšlel
- hodnotu se snažím předat pomocí reference - nechci vytvořit v paměti místo, kam bych hodnotu zkopíroval, a používal ve funkci tuto novou hodnotu - dávám přednost používat hodnotu původní (a potenciálně jí i měnit)
- const říká, že ale tu hodnotu NESMÍM ve funkci změnit - a překladač to má (při překladu) ohlídat.


S prvním bodem souhlasím Smile S druhým už ne - jak psal weny, může se ti stát, že překladač bude muset vytvořit dočasnou proměnnou s výsledkem, na kterou ti předá pointer. Ale i kdyby to dělat nemusel, tak na moderních počítačích je reference (pointer) větší nebo alespoň stejně velký jako int, takže místo v paměti tím spíš ztratíš.
Ale hlavně, "const int& X" říká, že X je reference na hodnotu, kterou TY nesmíš změnit. O tom, že X (nepřímo) nemůže změnit někdo jiný není řečeno ani slovo. Pro překladač to pak znamená, že X nemůže uložit do registru a musí pro něj sahat do paměti (což je ve srovnání se čtením z registru dost pomalé).

Lemik napsal:
const int& - někdo se usměje, co je to za blbost, kompiler prostě použije původní hodnotu a tuším ani neřeší že se jedná o referenci, což by řešil v případě ne-const reference, a někdo koukne a pochopí, že nejde o idiom "čekám, že tuto hodnotu změníš".


Spíš jde o idiom "neměň, ale čekej, že někdo jiný by mohl..."

Lemik napsal:
Ano, používat unique_ptr kvůli int* je blbost. Kdo to udělá, je asi až trošku moc nejistý, cvok nebo tomu totálně nerozumí. Pointery bych rozhodně nezmiňoval pro začátečníky - reference by měli znát mnohem dříve než pointery - opět by to byl špatný příklad, ale chtěl jsem vysvětlit ten pohled.


Reference je ukazatel, se všemi problémy, které z toho plynou. Vytvořit referenci inicializovanou jako null sice není tak triviální, ale mít referenci na smazaný objekt už není nic složitého. Proto mi dost vyhovuje třeba styl používaný v Google, kde se reference používají jen s const, jen pro složitější objekty a obvykle jen pro objekty, které volaná funkce po návratu už nebude používat. A na vše ostatní jsou pointery, protože u nich je na první pohled jasné, že se tam děje něco zvláštního.
_________________
http://trionteam.net
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Krolli



Založen: 12. 05. 2013
Příspěvky: 13

PříspěvekZaslal: 25. červen 2013, 20:06:03    Předmět: Odpovědět s citátem

Lemik napsal:
const int& - někdo se usměje, co je to za blbost, kompiler prostě použije původní hodnotu a tuším ani neřeší že se jedná o referenci, což by řešil v případě ne-const reference, a někdo koukne a pochopí, že nejde o idiom "čekám, že tuto hodnotu změníš".


Obávam sa, že prekladač pôvodnú hodnotu môže použiť maximálne v prípade, že danú funkciu inlinuje. Ak ale dojde k skutočnému volaniu, pôvodnú hodnotu použiť nemôže lebo nevie kde sa nachádza (pri každom volaní niekde inde, záleží na volajúcej funkcii) a nemôže ten int ani kopírovať, lebo by sa porušila vlastnosť referencie (hodnotu môže zmeniť niekto iný a prejaví sa to). Takže kompilátoru ostáva len predať na ňu pointer. Či to je pomalšie ako kopírovať primitívny typ je už otázne.

Možno som ale mimo a ľudia čo majú s prekladačmi a asm viac skúseností ako ja ma opravia. Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Tringi



Založen: 28. 07. 2007
Příspěvky: 289

PříspěvekZaslal: 25. červen 2013, 20:14:03    Předmět: Odpovědět s citátem

Pokud se to neprojeví na chování a výsledku tvého programu (nebo máš někde undefined behavior), může si překladač dělat (a taky že dělá) naprosto co chce. Cool
_________________
WWW | GitHub | TW
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
mar



Založen: 16. 06. 2012
Příspěvky: 602

PříspěvekZaslal: 25. červen 2013, 23:20:40    Předmět: Odpovědět s citátem

Krolli napsal:
Či to je pomalšie ako kopírovať primitívny typ je už otázne.


Příklad: add(2,3):

int add( int x, int y ):

kód:

mov eax, DWORD PTR _y$[esp-4]
mov ecx, DWORD PTR _x$[esp-4]
add eax, ecx
ret 0


int add( const int &x, const int &y ):

kód:

mov eax, DWORD PTR _x$[esp-4]
mov eax, DWORD PTR [eax]
mov ecx, DWORD PTR _y$[esp-4]
add eax, DWORD PTR [ecx]
ret 0


volání:

kód:

push   3
push   2
call _add
add esp,8


kód:

sub esp, 8
lea eax, DWORD PTR $T0[esp+8]
push eax
lea ecx, DWORD PTR $T1[esp+12]
push ecx
mov DWORD PTR $T0[esp+16], 3
mov DWORD PTR $T1[esp+16], 2
call _add
add esp,16


Posuď sám (kód MSC 2008, 32-bit x86, max. optimalizace, bez whole program optimization, s omit stack frame, volání a implementace v jiných modulech) Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Ladis



Založen: 18. 09. 2007
Příspěvky: 1533
Bydliště: u Prahy

PříspěvekZaslal: 26. červen 2013, 09:32:31    Předmět: Odpovědět s citátem

A zkoušel sto v něčem jiném než 5 let starém MSC? Wink
_________________
Award-winning game developer


Naposledy upravil Ladis dne 26. červen 2013, 09:34:11, celkově upraveno 1 krát
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1525
Bydliště: Telč

PříspěvekZaslal: 26. červen 2013, 09:33:53    Předmět: Odpovědět s citátem

A ty? :-) Myslíš, že se to nějak zásadně změnilo?
_________________
Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Ladis



Založen: 18. 09. 2007
Příspěvky: 1533
Bydliště: u Prahy

PříspěvekZaslal: 26. červen 2013, 09:34:45    Předmět: Odpovědět s citátem

V MSC asi ne, jako spousta věcí Wink
_________________
Award-winning game developer
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1525
Bydliště: Telč

PříspěvekZaslal: 26. červen 2013, 09:36:08    Předmět: Odpovědět s citátem

No jo, asi nám začne flame, co? :-)..můžem pak ještě pokračovat s tématem Windows versus Linux :-).
_________________
Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Tringi



Založen: 28. 07. 2007
Příspěvky: 289

PříspěvekZaslal: 26. červen 2013, 10:01:56    Předmět: Odpovědět s citátem

Ladis: Kód, tak jak ho popsal (volání napříč unitami), lépe zkompilovat z principu nejde.
Reference se zde musí implementovat adresou, protože pořád je možnost, že side-effect něčeho dalšího změní hodnotu původní proměnné (a tedy i hodnotu která je vidět přes referenci) během provádění té funkce.
_________________
WWW | GitHub | TW
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
mar



Založen: 16. 06. 2012
Příspěvky: 602

PříspěvekZaslal: 26. červen 2013, 10:02:43    Předmět: Odpovědět s citátem

Pro Ladise: gcc 4.7.2 (rok starý) s AT&T syntaxí Smile

rezervuje si zásobník, cleanup dělá až nakonec (MSC ale dělal něco podobného) - takže si tam ještě někde po volaní přidejte add esp, n

implementace:
kód:

   movl   8(%esp), %eax
   addl   4(%esp), %eax
   ret


kód:

   movl   4(%esp), %eax
   movl   (%eax), %eax
   movl   8(%esp), %edx
   addl   (%edx), %eax
   ret


volání:
kód:

   movl   $3, 4(%esp)
   movl   $2, (%esp)
   call   __Z3addii


kód:

   movl   $3, 28(%esp)
   movl   $2, 24(%esp)
   leal   28(%esp), %eax
   movl   %eax, 4(%esp)
   leal   24(%esp), %eax
   movl   %eax, (%esp)
   call   __Z4addcRKiS0_
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++ Časy uváděny v GMT + 1 hodina
Jdi na stránku Předchozí  1, 2, 3, 4, 5  Další
Strana 4 z 5

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna