Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: SDL_Surface vectoriin

Sivun loppuun

kayttaja-3842 [24.08.2009 22:04:07]

#

Tervehdys kaikille jälleen...

Pitää kyllä myöntää, että alkaa hieman jo hävettää, koska C/C++ alueella taitaa kohta olla ensimmäisellä sivulla pelkkiä minun perustamini aiheita. Suuri anteeksipyyntö tämän johdosta.

...noh, jottei tämä viesti mene aivan itkemiseksi, esitämpä tämän minun ongelmani. Eli tuli tuota softaani tekiessä pieni probleema SDL_Surface:en kanssa.

Eli ongelma on se, että hakiessani vectori "images":ta kuvan Draw funktiolle ja koitan piirtää ruutuun kuvaa, niin ohjelma kaatuu. Itse epäilen jonkin moisen muistipaikan nollautumista, mutta itse en näe koodissa mitää vikaa, mikä voisi kaataa ohjelman.

...tämä on todella vaikee selittää, joten teen niin, että jos tarvitaan lisä tietoa, niin kysykää, niin minäpä kerron. :)

Kiitos jälleen etukäteen todella paljon!!!

Tähän malliin

//IMAGE structi
  struct IMAGE{
    string name;
    SDL_Surface *surface;
  };

    class DRAW{

    public:
     //Constructori
     DRAW();
     //Ikkunan luonti
     bool CreateImage(string filename, string imgName);
     //Vapautus funktio (käy läpi vektorin jokaisen pinna, ja vapauttaa sen)
     void FreeSurfaces();
     //Hakee "nimen" perusteella kuvan vektorista
     SDL_Surface* getSurface(string imgName);
     //Piirto funktio
     void Draw(SDL_Surface *screen, string imgName, int x, int y);

    private:
     //Luo vektorin joka periytetään IMAGE sturctista
     vector<IMAGE> images;

  };

...tässä vielä draw.cpp funktioiden määrittelyt

#include "draw.h"

 DRAW::DRAW(){}

 bool DRAW::CreateImage(string filename, string imgName){
   //Luoda väliaikais kuvan
   SDL_Surface *tempSurface = SDL_LoadBMP(filename.c_str());
   //Luo IMAGE tyypisen väliaikais "olion"? ja tallentaa siihen nimen ja tempSurfacesta kuvan.
   IMAGE tempImg;
    tempImg.name = imgName;
    tempImg.surface = tempSurface;
   //Siirretään väliaikais IMAGE vektoriin
   images.push_back(tempImg);
   //Vapautetaan väliaikais pinta
   SDL_FreeSurface(tempSurface);
 }

 void DRAW::FreeSurfaces(){
      //Silmukka käy läpi vektorin ja vapauttaa niissä olevat pinna (käytetää ohjelman sulkeutuessa)
   for(int i = 0; i < images.size(); i++ ){
    SDL_FreeSurface(images.at(i).surface);
   }

 }

 SDL_Surface* DRAW::getSurface(string imgName){
  //Luo tyhjän pinnan varmuuden vuoksi, jos haettua kuvaa ei löydy
  SDL_Surface *empty;

   //Käy silmukassa läpi vektorin ja vertaa vastaako haetun kuvan nimi kuvan nimeä, jos vasaa palautetaan kuva
   for(int i = 0; i < images.size(); i++ ){
    if( imgName == images.at(i).name ){
      SDL_FreeSurface(empty);
     return images.at(i).surface;
    }
   }
 //Jos kuvaa ei löytynyt, palautetaan tyhjä pinta
  return empty;
 }

 void DRAW::Draw(SDL_Surface *screen, string imgName, int x, int y){

  SDL_Surface *drawSurface = getSurface(imgName);

   SDL_Rect rect;
    rect.x = x;
    rect.y = y;

    SDL_SetColorKey(drawSurface, SDL_SRCCOLORKEY, SDL_MapRGB(drawSurface->format,255,0,255));
    SDL_BlitSurface(drawSurface, NULL, screen, &rect);

   SDL_FreeSurface(drawSurface);
 }

kayttaja-2499 [24.08.2009 22:11:20]

#

Voisiko johtua siitä että vapautat kuvan/surfacen heti lataamisen jälkeen?

kayttaja-3842 [24.08.2009 22:14:01]

#

Mitä tarkoitat? Tarkoitatko siis kohtaa CreateImage-funktiossa, jossa vapautan tempSurface? Jos kyse on siitä, kokeilin jo ennen ennenkuin kirjoitin tänne, kommentoida tuon rivin poijes, mutta se ei auttanut.

kayttaja-2499 [24.08.2009 22:20:55]

#

tempImg.surface ja tempSurface ovat osoittimia, jotka osoittavat samaan paikkaan sillä hetkellä millä vapautat tempSurfacen.

En täysin hallitse c++:ssaa mutta eikö tuo empty-surfacekin ole null? Eli yrität vapauttaa nullia.

kayttaja-3842 [24.08.2009 22:35:43]

#

Eli siis siinä tapahtuu juuri sitä mitä epäilinkin, eli tieto joka siirretään vektoriin, osoittaa loppujen lopuksi tyhjään paikkaan. Eli käsittääkseni CreateImage-funktion jälkeen tieto, joka tallenetaan vektoriin on turhaa, koska itse tieto johon pointteri osoittaa on tuhoutunut? Tätäkö meinasit?

Tuota empty pinnan luonti onkin periaatteessa turha, olen kyllä kokeillu suorittaa ohjelmaa ilman että sitä luodaan, mutta ei auttanut. En kuitenkaan usko, että empty pinnan luonti olisi syy, vaan uskon ehkä ennemmin ylhäällä sepittämääni tekstiin.

Metabolix [24.08.2009 22:40:21]

#

SDL_FreeSurface(tempSurface);

Tämän jälkeen pinta on vapautettu. Koska koodissasi käsittelet vain osoittimia SDL-pintoihin, tempSurface ja tempImg.surface osoittavat samaan pintaan, ja kun vapautat pinnan, kumpikaan osoittimista ei enää toimi. Ainoa oikea ratkaisu on tavalla tai toisella pitää kirjaa siitä, tarvitaanko pintaa vielä, ja kutsua SDL_FreeSurfacea vasta, kun kyseistä kuvaa ei enää käytetä (eli kun se poistetaan vektorista).

Erityisen hankala ongelmasta tulee siksi, että delete ei nollaa osoitinta, eli koodin kannalta näyttää, että surface olisi vieläkin kelvollinen osoitin. Valitettavasti muisti on kuitenkin jo vapautettu, eli osoitin osoittelee haudan taakse.

kayttaja-2499 [24.08.2009 22:44:19]

#

kayttaja-3842 kirjoitti:

Eli siis siinä tapahtuu juuri sitä mitä epäilinkin, eli tieto joka siirretään vektoriin, osoittaa loppujen lopuksi tyhjään paikkaan. Eli käsittääkseni CreateImage-funktion jälkeen tieto, joka tallenetaan vektoriin on turhaa, koska itse tieto johon pointteri osoittaa on tuhoutunut? Tätäkö meinasit?

Juuri niin.

kayttaja-3842 kirjoitti:

Tuota empty pinnan luonti onkin periaatteessa turha, olen kyllä kokeillu suorittaa ohjelmaa ilman että sitä luodaan, mutta ei auttanut. En kuitenkaan usko, että empty pinnan luonti olisi syy, vaan uskon ehkä ennemmin ylhäällä sepittämääni tekstiin.

Saako SDL_FreeSurface-funktiota kutsua nullilla tai jo vapautetulla surfacella (randomilla muistipaikalla)?

kayttaja-3842 [24.08.2009 22:55:09]

#

Nytten se toimii!!! Kiitos paljon. :)

kayttaja-2499 [24.08.2009 23:17:53]

#

Metabolix kirjoitti:

Erityisen hankala ongelmasta tulee siksi, että delete ei nollaa osoitinta, eli koodin kannalta näyttää, että surface olisi vieläkin kelvollinen osoitin. Valitettavasti muisti on kuitenkin jo vapautettu, eli osoitin osoittelee haudan taakse.

Yksi tapa on opetella käytäntö, jossa osoitin asetetaan osoittamaan nullia, kun sen osoittama muisti on vapautettu. Sekä tutkia osoittaako osoittin nulliin ennen osoittimen käyttöä.

Metabolix [24.08.2009 23:34:26]

#

kayttaja-2499 kirjoitti:

Yksi tapa on opetella käytäntö...

Tietenkin tapoja on. Mitä ohjelmoinnista tulisikaan, jos bugit olisivat väistämättömiä? :) Tuossakin tilanteessa pitäisi silti joka kerta tarkistaa osoittimen arvo ja ehkä jättää kuva piirtämättä, joten ongelma ei ole ratkennut, vaan vasta sen suurin haitta (ohjelman kaatuminen) on estetty.

Tarkoitin oikeastaan, että ongelma on joskus hankala paikallistaa tai ohjelman toimivuus tarkistaa, kun kaikki vapautettuun muistiin osoittavat osoittimet eivät maagisesti muutu nulleiksi eikä mistään saa varsinaisesti selville, onko tietyn muistiosoitteen muisti sattumoisin vapautettu.

Ihan vain selvennyksenä. :)

koo [25.08.2009 13:50:15]

#

Kysyjän ongelma näyttää olevan siinä, että ajatukset osoitinmuuttujan arvosta ja siitä, mitä tuon arvon osoittamassa muistipaikassa on, menevät sekaisin. Surface ja siihen osoittavat osoittimet eivät ole sama asia, mikä ehkä alkoikin jo selvitä.

Osoitinmuuttujien nollaamisesta on keskusteltu ennenkin. Nollaaminen on tapauksesta riippuen joko tarpeellista, aivan turhaa tai suorastaan vahingollista. Ei siis kannata tuudittautua mihinkään käytäntöön vaan toimia tilanteiden mukaan.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta