1 / 31

Symbian ohjelmointi

Symbian ohjelmointi. 2. Luento Juha Turunen (juha.turunen@lut.fi). Perusfilosofiat Symbian ympäristössä. §1 Luotettavuus Ei muistivuotoja Kunnollinen poikkeuskäsittely §2 Pieni muistinkulutus Static footprint Run-time footprint §3 Nopeus. Sisältö. Poikkeustilanteiden käsittely

urbana
Download Presentation

Symbian ohjelmointi

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Symbian ohjelmointi • 2. Luento • Juha Turunen (juha.turunen@lut.fi)

  2. Perusfilosofiat Symbian ympäristössä • §1 Luotettavuus • Ei muistivuotoja • Kunnollinen poikkeuskäsittely • §2 Pieni muistinkulutus • Static footprint • Run-time footprint • §3 Nopeus

  3. Sisältö • Poikkeustilanteiden käsittely • Muistinhallinta • Cleanup stack • Olioiden kaksivaiheinen konstruktointi

  4. Miksei C-tyylinen poikkeuskäsittely riitä? • Jokainen tapaus tarvitsee tarkastaa erikseen tai käyttää try catch -rakennetta • Vie paljon tilaa (§2) if ( ( obj = new CObj() ) == NULL ) HandleException(); • Try-catch generoi runsaasti koodia • C++ konstruktoreilla ei ole paluuarvoa => ei voida tietää menikö jokin vikaan CMyObj()::CMyObj() { iSomething = new CSomething(); if ( iSomething == NULL ) // ?!? } • Keskeneräisesti konstruktoidut oliot (§1)

  5. Poikkeuskäsittely • Leave & TRAP harness • Symbian OS:ssa ei käytetä C++:ta tuttua try-catch-rakennetta poikkeustilanteiden hallintaan. • Try-catch-rakenteen tilalla käytetään ns. TRAP harness-mekanismia. • TRAP harness asetetaan seuraavasti: TRAPD( error, DoSomethingL() ); • Kun ohjelman suorituksessa sattuu poikkeus (leave), hyppää suoritus lähimpään TRAP harnessiin ja leave-koodi talletetaan muuttujaan (error). • Leaven aiheuttaminen • User::Leave( TInt aReason ); • ylikirjoitettu new-operaattori new( ELeave ) • tästä lisää muistinhallinnan yhteydessä • Metodien jotka saattavat aiheuttaa leaven pitää päättää nimensä L-kirjaimeen!

  6. Poikkeuskäsittely • Panic • Käytetään vakavan virheen sattuessa • Lopettaa threadin suorituksen • Applikaation pääthreadin kuoleminen tappaa muut threadit • Ohjelman suorituksen loputtua systeemi tulostaa infon, jossa lukee panicin aiheuttajan määrittelemä teksti sekä panic-koodi • Panicin aiheuttaminen • User::Panic(const TDesC& aCategory, TInt aReason ); • Panic on virheiden paikallistamista varten • Jos kaikki menee kuin elokuvissa, ei loppukäyttäjä koskaan nää panic-ilmoituksia

  7. Muistinhallinta • Muistin varaaminen • Käytetään C++ operaattoria new • Ylikirjoitettu new()-operaattori tukee leave-mekanismia • myStuff = new( ELeave ) CStuff; • mikäli muistinvaraus epäonnistuu, aiheutuu leave • Varattu muisti on nollattu systeemin toimesta • Jos muisti on nollattu jos systeemin toimesta, ei applikaatioiden tarvitse tyhjentää sitä => vähemmän koodia (§2)

  8. Muistinhallinta • Muistin vapauttaminen • Käytetään C++ operaattoria delete • delete-operaattorille voi antaa myös NULL-pointerin • Applikaatioiden ei tarvitse tarkistaa erikseen NULL-pointtereita > vähemmän koodia (§2)

  9. Muistinhallinta • Stack vs. Heap • Stack • Pino • Muistia ei varata kernelin kautta vaan pino-osoitinta kasvatetaan • Destruktoria kutsutaan, kun poistutaan skoopista • Muisti vapautuu pino-osoitinta vähentämällä • Ei C-luokkia stackiin! • Stackin määrä melko rajallinen • Heap • ”Kasa” • Muisti varataan kernelin kautta • Muisti vapautetaan ja destruktoria kutsutaan eksplisiittisesti delete-operaattorilla

  10. Stack & heap • Pointterit stackissa osoittavat olioihin heapissa { TInt i; CClass* c = new(ELeave) CClass; ... Stack Heap c CClass i

  11. Muistivuodot • Muistivuoto tapahtuu kun muistia varataan, mutta sitä ei vapauteta { Tint i; CClass* c = new(ELeave) CClass; c.Use(); // delete c; } Stack Heap CClass

  12. Muistivuodot • Symbian applikaatioissa muistivuodot ovat erityisen haitallisia, koska mobiililaitteissa muistia on vähän ja ohjelmat saattavat olla katkotta ajossa jopa kuukausia • Symbian-sovellus ei saa vuotaa muistia! • Loppukäyttäjät eivät miellä puhelinta tietokoneeksi • Muistivuotojen havaitseminen • Symbian OS tarjoaa mekanismin muistivuotojen havaitsemiseen mahdollisimman aikaisessa vaiheessa • Varattujen muistisolujen määrän täsmääminen voidaan varmistaa tietyissä pisteissä ohjelman suoritusta

  13. Pieni muistutus C++ konstruktoinnista • Luotaessa uusi olio new –operaattoria käyttäen, kutsutaan C++ luokan erityisiä konstruktorimetodeja • Class::Class() • Vastaava pätee myös olion tuhoamiseen jolloin metodeja kutsutaan destruktoreiksi • Class::~Class() • Luokan ollessa peritty kutsutaan kantaluokan konstruktoria ensin • Tuhottaessa käänteinen järjestys

  14. Cleanup Stack • Symbianin ratkaisu resurssien vapauttamiseen poikkeustilanteissa • Cleanup stackia tarvitaan, jotta varattu muisti voidaan vapauttaa hallitusti leaven sattuessa • ... • CStuff* myStuff = new( ELeave ) CStuff; • myStuff->DoStuff(); • someObject->MightLeaveL(); • CFoo* myFoo = new( ELeave ) CFoo; • ... • Mitä tapahtuu jos MightLeaveL() tainew ( ELeave ) CFoo aiheuttaa leaven?

  15. Cleanup Stack • Cleanup stack on nimensä mukaisesti pino • Leaven tapahtuessa, CleanupStack tuhoaa kaikki sinne laitetut oliot. • CleanupStack::PushL() • Cleanup stackiin voi laittaa ainoastaan CBasesta perittyjä olioita, jos on tarpeen kutsua destruktoria • CBase:lla on virtuaalinen destruktori, jota Cleanup stack tarvitsee osatakseen tuhota sinne laitetut oliot

  16. Cleanup Stack • Tehdään edellisen esimerkin koodista ns. ”leave safe” • ... • CStuff* myStuff = new( ELeave ) CStuff; • CleanupStack::PushL( myStuff ); • myStuff->DoStuff(); • someObject->MightLeaveL(); • CFoo* myFoo = new( ELeave ) CFoo; • CleanupStack::PushL • ... • CleanupStack::PopAndDestroy( 2 ); • // myStuff & myFoo • ... • Jos MightLeaveL() tai new ( ELeave ) CFoo aiheuttaa leaven, Cleanup stack tyhjennetään ja myStuff sekä myFoo tuhoutuvat => ei muistivuotoa

  17. Cleanup Stack • CleanupStack::PushL() • PushL() voi tehdä leaven?! • ... • CStuff* myStuff = new( ELeave ) CStuff; • CleanupStack::PushL( myStuff ); • PushL() tekee leaven vasta kun cleanup stackissa ei ole enää tilaa yhdellekkään osoittimelle • PushL():lle annettu osoitin pääsee aina cleanup stackiin ja leave tapahtuu vasta tämän jälkeen

  18. Kaksivaiheinen konstruktointi • Mitä tapahtuu jos C++ konstruktorissa on koodia, joka voi suorittaa leaven? • Esim CStuff::CStuff() { iTimeStamp = SomeLibrary::GetTime(); iFoo = new( ELeave ) CFoo; // oops.. iBar = new( ELeave ) CBar; // I did it again... } // somewhere in code CStuff* myStuff = new( ELeave ) CStuff; • Mitä tapahtuu jos CBar tai CFoo olion luonti suorittaa leaven? • Ohjelmoijalla ei ole mahdollisuutta laittaa oliota Cleanup stackiin ennen kuin konstruktorin koodi suoritetaan!

  19. Kaksivaiheinen konstruktointi • Ongelma kierretään käyttämällä kaksivaiheista konstruktointia • Kaksivaiheisen konstruktoinnin 1. vaiheessa olio luodaan normaalisti C++:n new –operaattoria käyttäen • 1. vaiheen jälkeen olio laitetaan cleanup stackiin • Tämän jälkeen suoritetaan 2. vaihe, jossa voidaan suorittaa koodia, joka voi tehdä leaven • Loppuun asti konstruktoitu olio jätetään cleanup stackiin tai otetaan sieltä pois riippuen siitä, mitä jatkossa on tarkoitus tehdä

  20. Kaksivaiheinen konstruktointi • CStuff::CStuff() // constructor { iTimeStamp = SomeLibrary::GetTime(); } void CStuff::ConstructL() { iFoo = new( ELeave ) CFoo; // it’s OK to leave iBar = new( ELeave ) CBar; } CStuff::~CStuff() // destructor { delete iFoo; delete iBar; } // Somewhere in code CStuff* myStuff = new( ELeave ) CStuff; CleanupStack::PushL( myStuff ); myStuff->ConstructL(); // 2nd phase CleanupStack::Pop();

  21. Kaksivaiheinen konstruktointi • Jos CBar-luokan luonti aiheuttaa leaven, on myStuff Cleanup stackissa ja sen destruktoria kutsutaan. • Destruktori tuhoaa iFoo:n ja iBar:n • iBar:n luontihan jäi kesken, mutta se ei haittaa, koska delete-operaattori hyväksyy myös NULL pointterin • Usein kaksivaiheinen konstruktointi kirjoitetaan staattiseen metodiin, jolloin sitä ei tarvitse kirjoittaa uudelleen joka kerta kun luokasta tehdään instanssi. • CStuff* CStuff::NewL() { CStuff* self = new( ELeave ) CStuff; CleanupStack::PushL( self ); self->ConstructL(); CleanupStack::Pop(); return self; }

  22. Kaksivaiheinen konstruktointi • NewL():n käyttö • CStuff* myStuff = CStuff::NewL(); // easy... • CleanupStack::Pushl( myStuff ); • DoSomethingL(); • myStuff->SomethingElse(); • CleanupStack::PopAndDestroy(); • Jos NewL():n jälkeen tehdään leaven aiheuttavia operaatioita kannattaa NewL():n jättää olio valmiiksi cleanup stackiin => NewLC() • C-kirjain metodin lopussa on merkki siitä, että metodi jättää jotain cleanup stackiin

  23. Kaksivaiheinen konstruktointi • Metodit, jotka jättävät olioita cleanup stackiin päättävät nimensä C-kirjaimeen. Luokan dokumentaatio kertoo mitä CS:iin jätetään. • NewLC() • static CStuff* CStuff::NewLC() • { • CStuff* self = new( ELeave ) CStuff; CleanupStack::PushL( self ); self->ConstructL(); return self; } • Säästää koodia (§2) mikäli NewL():n jälkeen kutsuttaisiin kuitenkin CleanupStack::PushL(). Nyt osoitin valmiiksi cleanup stackissa

  24. Kaksivaiheinen konstruktointi • Jos luokassa on sekä NewL() että NewLC() voidaan optimoida NewL() CStuff* CStuff::NewL() // Before { CStuff* self = new( ELeave ) CStuff; CleanupStack::PushL( self ); self->ConstructL(); CleanupStack::Pop(); return self; } CStuff* CStuff::NewL() // Optimized { CStuff* self = CStuff::NewLC(); CleanupStack::Pop(); return self; }

  25. Kaksivaiheinen konstruktointi • Luokan jäsenmuuttujia EI laiteta cleanup stackiin, koska destruktori tuhoaa ne • Mitä tapahtuu, jos näin kuitenkin tehdään? • Riittää että luokan käyttäjä huolehtii siitä, että joko luokan instanssi on cleanup stackissa tai siihen viitataan jäsenmuuttujassa jolleka kutsutaan deleteä destruktorissa

  26. Cleanup Stack ja ei-C-luokat • Cleanup Stackiin voi laittaa myös muitakin kuin C-luokkiin osoittavia pointtereita TText* buffer=( TText* ) User::Alloc( 100 * sizeof( TText ) ); CleanupStack::PushL( buffer ); // do something that might Leave CleanupStack::PopAndDestroy(); • Huomaa että ainoastaan varattu muisti vapautetaan! Destruktoria ei kutsuta • Cleanup Stack ei tiedä miten destruktoria kutsutaan

  27. Cleanup Itemit • RSomeServerSession session; • session.Connect(); • ... • // Something that might leave • ... • session.Close(); • Ongelma: session jää sulkematta mikäli kesken suorituksen tapahtuu leave

  28. Cleanup Itemit • TCleanupItem • Sisältää referenssin olioon, jota kutsutaan kun cleanup stack tyhjennetään • Mahdollistaa minkä tahansa resurssin sitomiseen Cleanup Stack mekanismiin • Template funktiot • CleanupClosePushL( T& ); • CleanupReleasePushL( T& ); RSomeServerSession session; session.Connect(); CleanupClosePushL( session ); ... // Something that might leave ... CleanupStack::Pop() session.Close();

  29. Konstruktointiin liittyviä asioita • Jos kaksivaiheinen konstruktori on tarjottu, kannattaa C++ konstruktori asettaa privateksi • Helpottaa binary compatibility asioissa • Jos peritään CBase:sta on jäsen data valmiiksi nollattu • Jos konstruktoinnissa pitää tehdä jotain mikä voi aiheuttaa leaven, käytä kaksivaiheista konstruktointia • Muista käyttää cleanup stackia automaattisia muuttujia ja dynaamista varausta käytettäessä • C++ konstruktori ei saa tehdä leavea!

  30. Destruktointiin liittyviä asioita • Tuhoa vain kerran • Uudelleen allokoitaessa aseta osoitin = NULL • delete iSomething; • iSomething = NULL; • iSomething = CSomething::NewL(); • Destruktorit eivät saa olettaa täydellistä konstruktointia • Destruktori ei saa tehdä leavea! • Muista vapauttaa kaikki varatut resurssit luokan destruktorissa

More Related