Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Muistialueen ylitys pinoluokassa

alottelijaa [08.08.2008 18:51:00]

#

Jostain syystä en saa tätä koodia linuxissa toimimaan jos vaihdan malloc:n ja free:n tilalle new&delete. Kellään ideoita?

#include <iostream>
#include <malloc.h>

#define SIZE 10

using namespace std;

class pino
{
	int seuraava, *puskuri[SIZE];
	public:
		pino() { puskuri[SIZE] = 0; seuraava = 0; }
		~pino() { free(puskuri[SIZE]); }
		void push(int z);
		void pop();
};

void pino::push(int z)
{
	puskuri[seuraava] = (int*)malloc(sizeof(int));

	*puskuri[seuraava] = z;

	seuraava++;
}

void pino::pop()
{
	seuraava--;
	cout << "otetaan pinosta: " << *puskuri[seuraava] << endl;
}

int main()
{
	pino lasse;
	lasse.push(2);
	lasse.pop();

	return 0;
}

Ohjelma kääntyy mukisematta mutta new&deleten kanssa herjaa käynnistäessä jostain muistialueen ylityksestä.

EDIT: OpenSUSE 11.0 on käytössä ja kääntäjä + ide on gcc/eclipse
EDIT2: Taitaa olla väärällä alueella kaiken lisäks :) linux ongelmat on varmaan yleistä keskustelua

EXTRA EDIT: Nuolaisin ennenkuin tipahtaa sama ongelma malloc:n kanssa. Nyt ohjelmaa tulostaa numeron 2 mutta kaatuu sen jälkeen. Debuggerin mukaan kaatuu viimeisellä rivillä :'(

hunajavohveli [08.08.2008 19:28:52]

#

En tiedä, eroavatko new ja delete mitenkään malloc():sta ja free():stä, mutta pino() on (ilmeisesti?) konstruktori, joka suoritetaan, kun pino-olio luodaan. Konstruktorissa suoritetaan rivi "puskuri[10] = 0". Tässä tapahtuu virhe, koska taulukon viimeinen alkio on indeksiltään 9. Debuggerin ilmoittamassa kohdassa en nyt ainakaan äkkiä näe mitään virhettä.

Metabolix [08.08.2008 19:35:30]

#

Koodissasi ei ole mitään järkeä.

puskuri[SIZE] = 0;

Asetat siis nollan puskuri-taulukon kohtaan SIZE, joka menee taulukon rajojen yli, kuten on selvää. Virhe tulee ilmi vasta ohjelman lopussa, kun havaitaan, että olet kirjoittanut yli dataa, johon ei olisi pitänyt koskea. Luot olion koodissa niin, että se varataan pinosta, joten ylikirjoitat pinoon tallennettuja tietoja, joita ohjelma käyttää taas main-funktion lopussa.

free(puskuri[SIZE]);

Vapautat kohdassa SIZE olevan osoittimen, siis sellaisen, joka ei edes kuulu taulukkoon. Sen sijaan et missään vaiheessa vapauta yhtäkään noista malloc-funktiolla varaamistasi palasista.

Mitähän järkeä on edes tehdä pinoluokka, jossa on staattisen kokoinen taulukollinen osoittimia? Mikset saman tien käytä kokonaan staattista taulukkoa tai tee pinoa "oikein" eli niin, että on vain yksi osoitin, jonka osoittaman muistialueen kokoa muutetaan?

Varmaankin kaipaat jotain tällaista, joskin kaikki olennaiset tarkistukset puuttuvat yhä:

class pino {
  int *taulu;
  int maara;
public:
  pino() {
    taulu = NULL;
    maara = 0;
  }

  void push(int x) {
    // Kasvatetaan määrää, varataan tilaa uuden määrän mukaan ja tallennetaan luku
    ++maara;
    taulu = realloc(taulu, maara * sizeof(int));
    taulu[maara - 1] = x;
  }
  int pop() {
    // Otetaan viimeinen luku, pienennetään määrää, vähennetään muistia ja palautetaan
    int x = taulu[maara - 1];
    --maara;
    taulu = realloc(taulu, maara * sizeof(int));
    return x;
  }
  ~pino() {
    free(taulu);
  }
};

C++ ei sisällä realloc-funktiota vastaavaa välinettä, vaan joudut varaamaan uuden muistialueen, kopioimaan vanhan datan sinne ja vapauttamaan sitten vanhan.

Jos oikeasti kaipaat pinoluokkaa, STL:n otsikko stack tarjoaa valmiin sellaisen.

alottelijaa [08.08.2008 20:27:21]

#

oho ei tullut huomattua noin yksinkertaista asiaa :D

Ja teen pinosta kyllä dynaamisen. tämä on vähän niinkuin testiohjelma toimiiko win/lin kaikki samalla lailla perussyntaksissa vaikka sillä ei taida olla mitään eroa käyttöjärjestelmien välillä :)

Vastaus

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

Tietoa sivustosta