Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Vapaa muistialue

vesikuusi [12.04.2011 20:51:06]

#

Lukemassani kirjassa suositellaan käyttämään vapaata muistialuetta, koska "Vapaalla muistialueella olevat kohteet säilyvät funktion päättymisen jälkeen". Kuitenkin, aiemmin mainitaan että, koska osoitin itse on paikallinen muuttuja, se menetetään funktion päättyessä ja syntyy muistivuoto eli new-operaattorilla varattu muisti jää käyttökelvottomaksi. Eli mitä hyötyä on vapaasta muistista, kun se kuitenkin jää käyttökelvottomaksi funktion loputtua, jos osoitin on paikallinen??

E: kyseessä siis C++

L2-K2 [12.04.2011 21:04:08]

#

Tämän tiedon perusteella on vaikea sanoa, mitä kirjassasi tarkoitettiin.

Esim. seuraava tapaus on ihan toimiva (olettaen, että siinä ei ole typoja):

char* varaaja(int koko)
{
    char* taulukko = malloc(koko);
    if (taulukko != NULL) {
        for (int i = 0; i < koko; i++) {
            taulukko[i] = 0;
        }
    }
    return taulukko;
}

tässä tapauksessa varatun muistin sijaintitietoa ei menetetä, koska se palautetaan paluuarvona, joten muistivuotoa ei synny.

EDIT: C++ ei poikkea paljoa tässä suhteessa C:stä, korvaat vain sanan "malloc(koko)" tekstillä "new char[koko]" ja teet virhetarkastelut (muistivarauksen onnistumisesta) C++:n tapaan.

jalski [12.04.2011 21:08:54]

#

Nyt kannattaa itsenäisesti miettiä ihan ajatuksella.

Hyvän ohjelmointitavan mukaisesti varattu muisti pitää aina vapauttaa, kun sitä ei enää tarvita. Jos tuota varattua muistialuetta tarvitaan muualla, kuin kyseisessä funktiossa, voi aina käyttää globaalia osoitinta tai sitten yksinkertaisesti palauttaa funktiosta osoittimen.

vesikuusi [12.04.2011 21:14:30]

#

L2-K2,

siis vapaa muisti tarkoittaa sitä, kun luodaan esim. osoitin

int *Pointer = new int;

tässä siis luodaan osoitin, joka osoittaa johonkin int-muodolle sopivaan osoitteeseen. En tajua tuossa koodissasi malloc()-funktiota, mikset käytä new-operaattoria?

ja jalski,

juu tässä sitä on pohdittu jo hetki ennen kuin tänne postasin. Ei vaan mee jakeluun, että mikä etu siinä vapaassa muistissa on verrattuna paikallisiin (tai globaaleihin) muuttujiin. Yhtä hyvinhän nekin voi palauttaa funktiosta?

L2-K2 [12.04.2011 21:35:47]

#

Tämäntyyppisten "monimutkaisempien" rakenteiden edut eivät tule esiin kuin erikoistapauksissa. Yleensä jos jossain toteutuksessa ei näe mitään etua, ei sitä kannata käyttää.

Tässä tapauksessa tämä rakenne on välttämätön esim. linkitetyn listan toteuttamiseen. Esim (huom. koodi ei todennäköisesti käänny):

struct solmu {
	int arvo
	struct solmu * seuraava;
};

void alusta_lista(struct solmu **alku, int arvo) {
	*alku = new struct solmu;
	(*alku)->arvo = arvo;
	(*alku)->seuraava = NULL;
}

/*
 * Lisätään arvo linkitettyyn listaan. (Lista täyttyy olla alustettu tässä
 * vaiheessa, jolloin siellä on vähintään yksi alkio.)
 */
void lisaa_arvo_listaan(struct solmu **alku, int arvo) {

	// Etsitään listan häntä.
	struct solmu * kulkija = * alku;
	while (kulkija->seuraava != NULL) {
		kulkija = kulkija->seuraava;
	}

	// Lisätään listan häntään uusi alkio.
	kulkija->seuraava = new struct solmu;
	kulkija->seuraava->arvo = arvo;
	kulkija->seuraava->seuraava = NULL;
}

jalski [12.04.2011 22:01:10]

#

Jos käyttämällesi kääntäjälle voi antaa parametrin, millä se tekee assembly listauksen objekti-tiedoston sijaan, niin kokeile sitä ja tutki listauksesta miten lokaalien muuttujien muisti varataan funktioissa.

Alla esimerkki omasta keskeneräisestä assemblyllä kirjoitetusta OS/2 WPS-luokasta.

samdisk_init proc near
    push      ebp
    mov       ebp, esp
    sub       esp, 0x0000001C ; varataan tila lokaaleille muuttujille

hab = [ebp-0x00000004]
hwnd_client    = [ebp-0x00000008]
hwnd_frame     = [ebp-0x0000000C]
flCreate       = [ebp-0x00000010]
somSelf        = [ebp-0x00000014]
client_data    = [ebp-0x00000018]
somThis        = [ebp-0x0000001C]

... ; tässä tehtäisiin jotain fiksua


; lopussa näet yleensä jotain tälläistä

    mov       esp, ebp
    pop       ebp
    ret
samdisk_init endp

EDIT: sorry, copy/pastasin väärän kohdan ensin ja rivit päin peppua.

vesikuusi [12.04.2011 22:54:06]

#

noniin, kiitos asiallisista vastauksista :)

Vastaus

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

Tietoa sivustosta