Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: Missä vika kun muisti vuotaa

Puhveli [18.10.2009 01:07:49]

#

Pidän itseäni vielä aika nyyppänä mitä tulee C:n dynaamiseen muistinhallintaan, mutta opettelen sitä hakkaamalla päätä näppikseen, kääntämällä ja yrittämällä uudestaan niin kauan, kunnes menee gcc:stä yskimättä läpi.

Sain kuitenkin tehtyä rakenteen, johon kasataan dynaamisesti tekstirivejä ohjelman suoritusaikana. Kaikki toimii jonkin aikaa, kunnes ohjelma yllättäen aina eri kohdissa kaatuu. En itse keksi tekstihärpäkkeestä itse mitään vikaa.

Jos tuon muuttaa vakiokokoiseksi (char row[128][128]) homma pelittää ainakin niin kauan kun sitä jaksan testata.

Tekstihärpäke:

typedef struct {
	char **row;
	int rows;
	int memSpace;
} STRINGLIST;

int addRow(STRINGLIST *dst, const char *content) {
	void *tempPtr;

	if (dst->rows >= dst->memSpace) {
		tempPtr = (char **)realloc(dst->row, (dst->memSpace + 10) * sizeof(char *));
		if (tempPtr == NULL) return 1;
		dst->row = tempPtr;
		dst->memSpace += 10;
	}
	if ((dst->row[dst->rows] = strdup(content)) == NULL) return 1;

	dst->rows++;
	return 0;
}

void initList(STRINGLIST *dst) {
	dst->row = NULL;
	dst->rows = 0;
	dst->memSpace = 0;
}

void freeList(STRINGLIST *dst) {
	int i;

	if (dst->row) {
		for (i = 0; i < dst->rows; i++) free(dst->row[i]);
		free(dst->row);
	} dst->rows = 0; dst->memSpace = 0;
}

Tällä tavalla sitä käyttelen, ja jossain kohtaa (ilmeisesti satunnaisen mallocin, reallocin tai freen kohdalla) ohjelma aina kaatuu:

initList(dst);
addRow(dst, "penis");
addRow(dst, "kakka");
freeList(dst);
addRow(dst, "foo");
addRow(dst, "bar");
addRow(dst, "lisätienesti");

Löydättekö te, arvon putkanyymit, tuosta jonkin tietyn kohdan, joka selittäisi kaatumiset? Muuten syy voi olla missä tahansa ns. "hupsikupsissa", jossa vaikka piirretään yli näytön rajojen tms. Minulla nimittäin oli aikaisemmin vastaava pulma, joka ratkesi muuttamalla dynaaminen taulukko vakiokokoiseksi.

map_ [18.10.2009 01:19:28]

#

freeList ei aseta dst->row -muuttujaa takaisin nulliksi, vaan sinne jää vanhan vapautetun taulukon osoite.

Puhveli [18.10.2009 01:23:27]

#

map_ kirjoitti:

freeList ei aseta dst->row -muuttujaa takaisin nulliksi, vaan sinne jää vanhan vapautetun taulukon osoite.

Pelastit myöhäisiltani, rakas *halaus*. Tuo selittää myös aiemman "vastaavan pulman", sillä voin vaikka vannoa, etten sielläkään muistanut tuota tehdä. Ajattelin, että "kyllähän minä itse nyt osaan katsoa, etten NULL-pointteriin sijoita mitään" ja unohdin täydellisesti käyttäväni reallocia. Kiitos vielä.

Metabolix [18.10.2009 12:37:19]

#

Muistutetaan nyt vielä termeistä, että muistivuoto tarkoittaa tilannetta, jossa free-kutsu puuttuu, ja ainoa tapa, jolla se voi suoraan johtaa ohjelman kaatumiseen, on resurssien (muistin) loppuminen. Tässä taas käytettiin virheellistä osoitinta, mikä on aivan oma virheensä, jonka tuloksena on usein segmentation fault tai page fault (tai joskus standardikirjaston sisäinen virhe).

Vastaus

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

Tietoa sivustosta