Zajmowanie pamięci

0

Dzień dobry.

Głowie się nad problemem, którego rozwiązanie mnie chyba przerasta:). Otóż napisałem duży program i zauważyłem, że w trakcie działania programu mam prawdopodobnie zajmowaną, lecz niewykorzystywaną pamięć. Zastanawiam się, czy jest możliwe, że mam wyciek pamięci mimo, że nie używam wskaźników?
Pracuję na Microsoft Visulu, system Windows 7 (o ile to istotne). Pobieram i zapisuje pliki binarnie, zawsze zamykam, korzystam z iteratorów, korzystam z list i stringów. Jak już wspominałem, z wskaźników nie korzystam. Zmiany w pamięci są bardzo duże (np 300 KB)

0

String i list korzystają z dynamicznej alokacji pamięci. Jesteś pewien że nie tworzysz dużych stringów albo długich list?

0

Stringi u mnie są bardzo krótkie (do 10 znaków) więc one nie mogą być przyczyną. Co do list to faktycznie tworze je bardzo duże.
Może pogrupuje w etapy, zeby latwiej pokazac problem
poczatek programu 300 KB
pobieram i pakuje tekst z pliku do listy 1500 KB
czyszcze (poprzez clear) liste 700 KB
wartości podane tutaj są orientacyjne. Podobnie trace 4 KB przy zapisie do pliku.

Dodam jeszcze fakt, ze ilosc rezerwowanej pamięci sprawdzam w Menedżer Windows w procesach w rubryce pamięć (prywatny zestaw roboczy). Może w tym momencie robię coś źle? Przyznam się, że nigdy tego nie badałem.

Na samym końcu dodam fakt, że wielkość traconej pamięci zależy od wielkości pobieranego pliku. Uruchamiam wersje release i nie wiem czy po wylaczeniu programu pamiec jest zwalniana (nie wiem jak to sprawdzic). Program zajmuje dziwine duzo pamieci (utrzymanie 17- MB pliku w postaci listy (unsigned char) wymaga od niego uzyca 600MB RAM-u). Pamięć prawdopodobnie jest zwalniana przy wyłączaniu programu, natomiast irytuje mnie strata pamieci w czasie dzialania programu.

0

Na podstawie samego menedzera zadan nie da sie zdebugowac memory leakow. Przy czytaniu/zapisie do pliku system sobie wrzuca do cache'a to co przeczytales/zapisales wiec nic dziwnego, ze zuzycie pamieci rosnie.

Program zajmuje dziwine duzo pamieci (utrzymanie 17- MB pliku w postaci listy (unsigned char) wymaga od niego uzyca 600MB RAM-u).

Czyli rozumiem, ze kazdy znak trzymasz jako osobny element listy? W takim razie:
17MB plik ma 1710241024/8 = 2228224; znakow. Element listy w programie x64 zajmuje 24 (2 wskazniki + char + alignment) bajty czyli ogolnie lista zajmuje conajmniej 24*2228224= 51MB. Dolicz sobie do tego ~25% meta informacji uzywanej przez sterte wyjdzie z 60MB. Nawet jak doliczyc, ze caly plik idzie do cache'a to maksymalnie program moze zajmowac ~90MB. Jezeli zajmuje Ci 600MB to masz cos nie tak.
Ustal w ktorym momecie masz taki duzy skok zuzycia do 600MB - czy to jest po dodaniu elementow do listy czy kiedy indziej.

0

Chodzi najprawdopodobniej o ten kawałek kodu:

while ( !plik.eof() )
	{
		plik.read((char*)&tmp,sizeof(char));
		tekst.push_back(  tmp);
	}

plik to oczywiście u mnie zmienna plikowa, tmp to char. tekst to list <unsigned char="char">. W tym momencie pobieranie 17MB plik wymagało ode mnie kilkaset MB RAM-u Sprawdzałem na bieżąco Zanim pętla zakończyła pobieranie.

Ciekawe, ze jak zamykalem plik przez funkcje close(), to nie zauwazylem, zeby komputer zwolnil pamiec (ciagle badam w meneger).

0

Jaki jest w ogóle sens trzymania tego w liście? Dlaczego nie liniowy wektor?

@0x200x20, dlaczego podzieliłeś ilość bajtów przez 8? Każdy ze znaków trzymasz w jednym bicie? 24 bajty * ilość znaków to już 408MB.

0

Tak jak ci podliczył @0x200x20 masz z grubsza 24 bajty na znak, czyli przy pliku 17 MB ma prawo zajmować 408 MB więcej niż dotychczas.

0

Przyznaje, ze słabo znam binarne operacje na plikach. W którym momencie dziele przez 8? Poza tym niestety potrzebuję listy, ponieważ potrzebuje miec mozliwosc szybkiego usuwania i podmieniania ciągów tekstu, a wektor mi tego nie gwarantuje.

EDIT: mój błąd pomylilem posty:) Ale nie rozumiem czemu jeden znak zajmuje mi 24 bajty a nie 3.

0

Bardzo dziękuję za odpowiedź:) Jeszcze jedno pytanie - czy można jakoś sprawdzić rozmiar listy? sizeof nie pomaga mi w tej kwestii. Tak samo interesuje mnie rozmiar tablicy list.

0

list<char> MOJA_LISTA;
cout<<"elementów: "<<MOJA_LISTA.size();
cout<<"baytów: "<<(24*MOJA_LISTA.size()+sizeof(MOJA_LISTA));
http://www.cplusplus.com/reference/list/list/size/

0

a zakładając, że nie wiem czy pojedynczy element listy zajmuje 24 bajty?

0

Możesz się domyślać albo przejrzeć implementację standardowej biblioteki, z której korzystasz. Nie ma automagicznego sposobu na to, bo np. nie wiadomo jak podążać za wskaźnikami. Przykładowo - czy coś będące pod wskaźnikiem będącym elementem listy jest jeszcze listą? Kompilator ani runtime tego nie wie - ty tak.

1

Zajrzeć do folderu include twojego kompilatora, znaleźć deklarację listy zobaczyć jak się nazywa i podać jako argument sizeof.
Np dla g++ będzie to:
cout<<sizeof(_List_node<char>)<<endl;

1

W Visual C++ to std::list<char>::_Node albo std::_List_node<char, void*>, ale potraktuj to raczej jako ciekawostkę i w normalnej aplikacji nie wykorzystuj jawnie wewnętrznych struktur bibliotek. W tym przypadku to podkreślenie na początku nazwy właśnie to sugeruje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1