Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Muistialueen laajentaminen (C, malloc)

Burton [11.09.2008 22:43:30]

#

Terve taas,
olen pohtinut, kuinka C:llä toteutetaan muistinlisäys muuttujalle, jolle on jo kerran jaettu malloc-funktion avulla muistia. Eli näin:

int i, *m = NULL;

m = malloc(50 * sizeof(int));
for (i = 0; i < 50; i++)
{
      m[i] = i;
}

m = malloc(70 * sizeof(int)); // Näin se EI onnistu, mutta tästä näkee, mitä haen takaa
for (i = 50; i < 70; i++)
{
      m[i] = i;
}

free(m);

Kävin jo pari vaihtoehtoa mielessäni läpi, mutta paras niistä kuuluisi näin:

// Muisti on varattu jne.
int *tmp = NULL;

tmp = malloc(50 * sizeof(int));
for (i = 0; i < 50; i++)
{
      tmp[i] = m[i];
}
free(m);

m = malloc(70 * sizeof(int));
for (i = 0; i < 50; i++)
{
      m[i] = tmp[i];
}
for (i = 50; i < 70; i++)
{
      m[i] = i;
}
free(tmp);

...joka ei kuitenkaan ei tunnu siltä parhaalta vaihtoehdolta. Ehdotuksia?

Antti Laaksonen [11.09.2008 22:47:52]

#

Funktio realloc muuttaa aiemmin varatun muistialueen kokoa.

Burton [11.09.2008 22:53:27]

#

No sepä kävi näppärästi! Kiitos kovasti. :)

Metabolix [11.09.2008 23:19:35]

#

Kannattaa muistaa, että vaikka realloc säilyttääkin muistissa olevan datan, sen palauttama osoitin ei välttämättä ole sama kuin ennen (esimerkiksi jos kyseiseen muistikohtaan ei mahdu vaadittua palasta). Seuraavassa ohjelmassa saattaa siis tapahtua virhe:

char *muisti, *kopio;

muisti = malloc(10);
kopio = muisti;

muisti = realloc(muisti, 20);
kopio[0] = 'a'; // Virhe! Voi olla, että kopio[0] osuukin nyt jo vapautettuun kohtaan.

free(muisti);

Jos ohjelman on tarkoitus selvitä myös siitä virhetapauksesta, että muistin varaaminen epäonnistuu, vanha osoitin on hyvä ottaa talteen ennen kutsua:

void *ptr = malloc(koko_a);
void *tmp;

tmp = realloc(ptr, koko_b);
if (!tmp) {
  // Pieleen meni, mutta vanha alue säilyy silti.
  printf("Virhe varauksessa! Varattua tilaa ei muutettu.");
} else {
  // Varaus onnistui, otetaan uusi osoite käyttöön
  ptr = tmp;
}
free(ptr);

Vastaus

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

Tietoa sivustosta