Linus taggelte a 2.6.36-rc8-at

Címkék

Ugyan volt esély arra, hogy a hetedik kiadásra jelölt verziót már nem követi újabb a 2.6.36-os kernel fejlesztési ciklusában, Linus azonban mégis úgy döntött, hogy tol egy újabb -rc-t. Bejelentés ugyan (még) nem érkezett az LKML-re, de az tisztán látszik, hogy taggelve lett a 2.6.36 nyolcadik -rc-je. Mivel egyre közelebb vagyunk a végleges 2.6.36-hoz, érdemes egy pillantást vetni a vele érkező változásokra.

Hozzászólások

XSAVE/XRSTOR live migration support

Ezt esetleg tudja valaki mit jelent pontosan?

Hová az a nagy fejlődés? 10 változattal előbbi olyan szépen teszi a dolgát.

Mert goto nélkül nem tudod elkerülni azt, hogy a hibakezelő kódod redundánsan többször be kelljen írni. Sok helyen láttam ezt a megoldást, bár van aki azt mondja, hogy a goto-t tűzzel vassal irtani kell. Te ez utóbbiak közé tartozol?

Persze írhatta volna fordítva is a feltételt, és akkor lespórol egy goto-t, de akkor sérül az, hogy mindig a hibaágat vágja le if-fel, ami a szokásos megoldása szokott (gondolom) lenni.

pentium1 ota a processzor statisztikakat keszit a programrol, hogy a programozo a felteteleknel milyen logikaval dogozik, igy a branchelesek eseten nagyobb valoszinuseggel tudja eldonteni, hogy melyik agat prefetchelje, ez altal gyorsabban fut le a kodod, ha tartod magad bizonyos konvenciokhoz. Goto-t meg a kodmeret optimalizalasa miatt szoktak alkalmazni a kernelbe, hogy ne legyen meg ugyan az a kodreszlet N+1-szer ugyan abban a fileba.
___
info

Azért ennek a hatékonysága kicsit urban legend. Eleinte én is hittem az ilyenekben, aztán elkezdtem CPU performance counterekkel játszani és kiderült, hogy ez milyen gyakran nem jön be.

Létezik olyan, hogy statikus elágazásbecslés, de a fordítón el szokott bukni ennek a hatékonysága.

A statisztika dinamikus elágazásbecslésnél működik, ahhoz viszont a kódnak egynél többször kell futnia (leginkább ciklusmagban sokszor). Ott meg tök mindegy, hogy melyik elágazásnál melyik ág a hibakezelő és melyik az alapeset, minden (táblázatban éppen beérő) elágazásra külön van bimodális számláló.
---
Internet Memetikai Tanszék

van aki azt mondja, hogy a goto-t tűzzel vassal irtani kell.
Szerintem az nagyjából helyes, hogy a programozás oktatáskor, amikor a C nyelvvel először találkoznak a hallgatók, akkor azt mondják nekik, hogy "ne használjanak goto-t". Ellenkező esetben boldog-boldogtalan azonnal mindenféle zavaros ide-oda ugrálós gányolásokra rászokna, ahelyett hogy megpróbálná a problémát rendesen függvényekbe, állapotgépekbe, ciklusokba, rekurziókba, stb. szervezve megoldani.

Ha valaki már tud C-ben gondolkodni goto-k nélkül, akkor lehet óvatosan, fegyelmezetten bizonyos vezérlési konstrukciókra (pl try/catch/finally) bevezetni a goto-k használatát. Fontos, hogy akkor is magát a konstrukciót lássuk meg és abban gondolkodjunk, ne abban, hogy éppen goto-t használunk. Különben nagyon gyorsan spagettikóddá változik, amit írunk és a végén mi sem ismerjük ki magunkat benne.

Szóval szerintem nem az a lényeg, hogy a goto tilos lenne, hanem az, hogy amikor először találkozik valaki C-vel, akkor még tilos a goto. Csak sok ember fejében ez később nem tisztul le, hogy eredetileg ezért nem volt szabad.
---
Internet Memetikai Tanszék

Milyen egyéb módszerek vannak C-ben exception jellegű hibakezelésre? (Arról gondolom nem kell vitát nyitnunk, hogy erre szükség van...)
A setjmp/longjmp egyrészt nem mindenhol alkalmazható, másrészt sokkal több problémát vet fel, mint a goto.

A goto helyes használatával nagyon jól átlátható, karbantartható kódot lehet készíteni.

Egyébként pedig ha a teljes függvényt megnézed, akkor látható, hogy mindenhol ezt használja a hibák lekezelésére.

Inkább az a szomorú, hogy még mindig vannak olyan helyek, ahol azt tanítják, hogy a goto káros. Ennyi erővel a ciklusok is, hiszen lehet végtelen ciklust írni.

Amivel nem értek egyet a fenti kódban, az annak az engedélyezése, hogy if és ciklus utasításokat blokk nélkül használjanak a kernelforrásban (vagy bárhol). Nagyon sok olyan hibával találkoztam különböző reviewkon, amik abból fakadtak, hogy korábban egy utasítás volt a ciklusban, aztán kellett mögé / eléírni még egyet, de a { } már lemaradt.

Üdv,
Gergely

"A goto helyes használatával nagyon jól átlátható, karbantartható kódot lehet készíteni."

pont ez miatt vetettem fel, mert számomra az, ha olvasom a kódot, akkor egy goto kiugrása valahová a procedura aljára, ehhez oda kell görgetni, a cimke környékén lévő kódot megérteni, majd visszaugrani hol tartottam, és tovább vizsgálni a működést.. főleg ha sok goto beszúrás van - ez nehezíti a megértést.

optimalizáció szempontjából nem tudom hogy jobb-e a compiler-nek a goto, meg biztos nálam sokkal jobban ért hozzá az aki ezt írta, de ez nem lenne olvashatóbb?


fail() { fprintf(stderr, "%s\n", strerror(errno)); }

...
	if (len >= 0) { fail; return 1}
....
            	if (akarmi < 0) { fail; return 1}

	return 0;
}

ez csak szőrszál hasogatás részemről kikapcsolódásként most.. :)

Nyilván a hibakezelés nem abból áll a legtöbb helyen, hogy kiírod a hibaüzenetet.

Hiba esetén a legfontosabb, hogy fel kell szabadítanod a lefoglalt erőforrásokat (memória, fájlleírók ... stb.). Ezeket általában nem lehet / nem érdemes egy külön függvénybe kiszervezni.

A másik hasznos dolog, hogy nagyon sokszor így néz ki a függvényed


eroforras1 foglalasa
if (hiba) {
result = FAILURE1;
goto hiba1;
}

eroforras2 foglalasa
if (hiba) {
result = FAILURE2;
goto hiba2;
}

eroforras3 foglalása
if (hiba) {
result = FAILURE3;
goto hiba3;
}

hipertitkos algoritmus cenzúrázva
result = SUCCESS;

hiba3:
eroforras3 felszabadítása
hiba2:
eroforras2 felszabadítása
hiba1:
eroforras1 felszabadítása

return result;

Nyilván 1-2 makróval ezt sokkal kényelmesebbé lehet tenni, nem kell külön állítgatni a result kódot.

Természetesen amikor valóban defenzíven programozunk, akkor kb. minden egyes függvényhívás után következik 5 - 10 sor hibakezelés. Ilyen esetben még inkább fontos, hogy rendben legyenek a hibakezelési útvonalak.

Eszerint a kódod így nézne ki

csinálvalamit(param1, ...) {
}

static void csinálvalamit_cleanup(eroforras1, eroforras2, ... eroforrasN) {
}

Ez szerintem rondább mint a goto, és nehezebben kezelhető, mert nem a helyükön vannak kezelve a dolgok:
1. Ez a cleanup függvény le fog zárni fájlokat, hálózati kapcsolatokat, felszabadít memóriát... stb. látszólag értelmetlen összevisszaságban, ha a másik függvénnyel nem együtt nézed.

2. Ráadásul külön figyelned kell arra, hogy a megfelelő sorrendben végezd a cleanup-ot, amely sorrendnek ismét csak a csinálvalamit() függvénnyel együttesen nézve lesz értelme.

De persze nekem mindegy, hogy csinálod...:)

Üdv,
Gergely

Milyen egyéb módszerek vannak C-ben exception jellegű hibakezelésre?
vmikor csinaltam/csinalok ilyesmit:


do 
 { ...
   if ( egyik_hiba ) break;
   ...
   if ( masik_hiba ) break;
   ...
 } while(0);

ez szerintem byterol bytra ugyanarra a kodra fordulna mint a goto-s megfelelo" (a cimke a while(0) helye'n van ertelemszeruen), csak nincs benne goto :] persze ez sem az igazi (ciklusokbol menekulni nehezebb) de az ilyen "menj vegig x eseten, es ha barmi geba van, akkor ugorj ki" esetekre jo akkor ha epp lusta vagy fv-t irni es/vagy az vmi miatt kenyelmetlen lenne es/vagy tobb hibalehetoseget rejt (sok valtozot kene atadni, amiknek megvaltoztathatja neha-neha az erteket, stb-stb). ez kicsit talan atmenet a klasszikus ganyolas es a java-fele megoldas kozott (cimkezett break-ek). meg me'g php-ban is jol lehet hasznalni, ha teljesen proceduralisan hasznalja aztat az ember.