Apró körültekintés a Vista forráskódban

Kb. két hete felrakták a forráskódokat tartalmazó szerverre a Vista forráskódját is (az MVP-séghez lehet kérni a hozzáférést, én éltem vele, használom is rendszeresen). Pont jól jött, mert az ActiveX Installer Service nem hallgat rám, pedig a munkámhoz ezt be kell konfigurálni majd az ügyfeleknek.
Debugolni lenne a legegyszerűbb ilyenkor, de egyelőre még nincs Vista kompatibilis kártyaolvasó driver, így marad az XP alóli kódböngészés (nyilván marha nagy secu van, nem csak jelszó alapú a hozzáférés).
Természetesen a kódokról nem beszélhetek direktben, főleg nem pasztázhatok be ide a blogba belőlük, de egy apróságot megosztok veletek, tetszett.
A Debugging Windows Applications könyv óta nagy szerelmese vagyok az Asserteknek. Az az igazság, míg nem olvastam a könyvet nem értettem, mire is való az assert? Azért nem értettem, mert ha úgyis van pl. egy függvényben paraméter ellenőrzés, ami exceptiont dob, vagy E_INVALIDARG-ot ad vissza, ha nem stimmel valami, akkor minek duplikálni az ellenőrzést még ASSERT-ekkel is? Nos, azért, mert az assert kiváltódása esetén egy gombnyomásra elindul a debugger, és benn vagyok a hibás részben, abban a kódrészletben, ahol nem teljesül az általam elvárt feltétel (invariáns, a tudományos neve? :). Mésként lehet, hogy csak 5 szinttel feljebb derülne fény a hibára, amikor már nem ismertek a mélyebben hibázó metódus lokális változó értékei, hisz a verem lebomlott. Tképpen az assertekkel a követelmények egy részét kódolja az ember a kódba, és egyúttal önvédelmet épít be a saját hibái ellen.

No, vissza a forráskódhoz. Az ieinstal.exe forrását nézegetem, hátha rájövök, miért nem úgy működik, ahogy szeretném. A forrás C++-ban íródott, nem C-ben. (Az oprendszer vegyesen asm, C és C++ kódokból épül fel.)
COM alapú, ezért tele van HRESULT kezeléssel. Ugye ez a hagyományos, status kód alapú hibakezelés, ami, ha csak if-elseket használunk nagyon mélyen betolt kódblokkokkat eredményezne. Ezt megelőzendő vagy exceptionkezelést használunk, vagy gotokat. Az első megoldás C++-ban nem annyira elterjedt, inkább managed és script környezetben használják elterjedtebben (de lehet, hogy csak nem értek hozzá). C++ kódokban gyakoribb a goto használata. if (FAILED(hr)) goto ErrorExit. Így sík lesz a kód, nem agyonindentált.
Az tárgyalt forráskódban szinte minden metódusban van két kijárat, egy sikeres és egy sikertelen, ahová gotoval ugrik be a szerző. Érdekes a következő. A sikeres kijáratnál vagy egy ilyen sor: ASSERT(SUCCEDED(hr)). A hibás ágnál: ASSERT(FAILED(hr)). Azaz a debug kód ellenőrzni, hogy ha egyszer a sikeres ágra engedtük a kódot, akkor ne adjunk már vissza véletlenül hibára utaló HRESULT-ot, és fordítva.
Apró, de szellemes trükk.
Mellesleg én sokáig legacynek éreztem a statuskód alapú hibakezelést, ez volt a .NET-es tankönyvekben is. Zoxigen annak idején adott egy linket, ahol Raymond barátunk rendberakta a fejemben a kérdést. Kötelező olvasmány. Van utójáték is a témához.
Mióta ezt olvastam mindig írok az if-ek mellé else-t még akkor is, ha abban nem csinálok semmit. Ilyenkor egy commentben odaírom, hogy ebben az ágban nincs teendő, de legalább látom, hogy nem feledkeztem meg róla.

Comments are closed.