'out of memory' - czy rzeczywiście ?

0

hej ! moja aplikacja jest dość pamięciożerna. i fajnie, tak widocznie musi być.
próbując jednak ostatnio uruchomić ją względem wszystkich plików na dysku, otrzymałem błąd out of memory. tymczasem wdg menadżera zadań aplikacja używała dopiero 250mb, a wolnych było jeszcze 600. czy bezwzględnie oznacza to że w którymś momencie program PRÓBOWAŁ sobie zarezerwować np 700 mb czyli więcej niż jest dostępne (co jednak uważam za niemożliwe) i stąd ten komunikat, czy może chodzi o coś innego, a jak tak to co ?

0

może chodzi o stacksize. wciśnij 'Ctrl-o' i jeszcze raz 'o'. Przyjrzyj sie dyrektywom {$M} poniżej wkleiłem ich opis z helpu

{$M minstacksize,maxstacksize}
{$MINSTACKSIZE number}
{$MAXSTACKSIZE number}
Default {$M 16384,1048576}
Scope Global
Remarks

The $MINSTACKSIZE and $MAXSTACKSIZE directives are used in Windows programming only. For information about the $M ($RESOURCERESERVE) directive in Linux, see Reserved address space for resources.
The $M directive specifies an application's stack allocation parameters. minstacksize must be an integer number between 1024 and 2147483647 that specifies the minimum size of an application's stack, and maxstacksize must be an integer number between minstacksize and 2147483647 that specifies the maximum size of an application's stack.

If there is not enough memory available to satisfy an application's minimum stack requirement, Windows will report an error upon attempting to start the application.
An application's stack is never allowed to grow larger than the maximum stack size. Any attempt to grow the stack beyond the maximum stack size causes an EStackOverflow exception to be raised.
The $MINSTACKSIZE and $MAXSTACKSIZE directives allow the minimum and maximum stack sizes to be specified separately.

The memory allocation directives are meaningful only in a program. They should not be used in a library or a unit.
For portability considerations between Windows and Linux, you should use the long forms of these directives instead of $M.

Note The $M directive is used for a different purpose on platforms other than Windows. See Reserved address space for resources.

0

hej !
no więc tak, problem okazał się być inny. MAXSTACKSIZE miałem ustawiony maksymalny, więc zacząłem odchudzać wykorzystywane zasoby licząc na to że błąd w końcu zniknie. ale nie znikał. w sumie cieszę się, bo uświadomiło mi to ile niepotrzebnie rzeczy trzymałem w pamięci. problemem była fragmentacja pamięci, najwyraźniej. jakoś dotychczas nie miałem okazji zetknąć się z tym zagadnieniem a tu masz, gruchnęło. konkretnym winowajcą była tablica dynamiczna, powiększana przez czas działania programu 123000 razy, po jednym elemencie. należy z tym postępować tak jak klasa TStringList ze swoimi zasobami, to jest przez rozróżnienie 'właściwości' Count i Capacity i zastosowanie odpowiednika funkcji Grow tejże klasy. czyli zwiększać tablice skokowo, poprzez jakąś stałą liczbę bądź procent aktualnego rozmiaru.
pozdrawiam !
//edit: literówka

0

SNW - czy możesz napisać coś więcej?
Ja mam podobny problem ze swoją aplikacją w Delphi i nie udaje mi się go rozwiązać. Problemem nie jest na pewno rozmiar stosu, bo inaczej zgłoszony byłby błąd typu EStackOverfow, a nie EOutOfMemory. Nie rozumiem czemu nie ma pamięci dla tablicy alokacji 100MB skoro wolne jest 1GB. Innymi słowy aplikacji jednocześnie widzi i nie widzi pamięci. Nie logiczne!

Co fragmentacja pamięci może mieć wspólnego z takimi błędami?
Ja u siebie podejrzewałem jakieś wycieki pamięci, ale tak dużych na pewno nie ma. Poza tym pamięć, która wyciekła, byłaby dla systemu widoczna jako zajęta, a tak nie jest - widzę to zarówno w Mangerze Zadań Windows (zakładka Wydajność) jak i pod debuggerem korzystając z obiektu tymu TMemoryStatus.

0

czy wycieki masz czy nie, sprawdź np MemProofem, nie zdawałbym się na metody opisane przez ciebie (100MB zauważysz ale kto powiedział że to one są winne). a co do fragmentacji no cóż, kieruję się tu raczej intuicją i zdrowym rozsądkiem (czytaj: nie wynika to z mojej stricte wiedzy a raczej z domysłów): jeżeli powiększam blok pamięci to zwalniam obszar który zajmuję i w innym miejscu tworzę nowy, powiększony. jeżeli będę to robił chaotycznie to suma wolnej dostępnej pamięci będzie się zgadzać ale będzie ona mocno pofragmentowana (jak na HD), w pewnym momencie nie udostępniając odpowiednio dużego bloku na kolejny resajz bloku danych. jeśli nie mam racji to niech ktoś mnie wyprowadzi z błędu :D. aha, jeśli byś nie wiedział: taka tablica czy w ogóle struktura danych, jest strukturą ciągłą w pamięci i nie można jej rozlokować po kątach (czyli w Twoim przypadku potrzebujesz 100MB ciągłej, wolnej pamięci). może coś pomogłem...

//edit: z drugiej strony za kazdym razem zmieniajac rozmiar tablicy zwalniam ja co w sumie napisalem, wiec de facto moje rozumowanie jest bez sensu...tak wiec nie rozumiem tego za bardzo. w programie mam jednak cale mnostwo list i to widocznie ich wzajemna lokalizacja w pamieci byla problematyczna, przy takim rozwiazaniu jakiego uzylem (powiekszanie po jednym elemencie jednej z tablic). dla mnie wazne jest ze zmiana kodu w sposob wyzej opisany ewidentnie rozwiazala ten problem u mnie :)

0

Z tą alokacją po jednym elemencie to nie dobry pomysł. Nie wiem jak to się ma do błędów o których pisałeś na początku, ale na pewno ma to pośredni wpływ na wydajność i to bardzo duży. Kiedyś jak się zaczynałem bawić programowaniem, miałem takie zadanie w pracy (niezwiązanej z programowaniem), aby usunąć powtórzenia z pewnego zbioru danych (kilka, może kilkadziesiąt tysięcy elementów). Na początku wczytywałem to z użyciem SetLength(x, Length(x) + 1) ;] Program był bardzo pożyteczny, więc wszyscy pokornie czekali, aż pasek postępu przejdzie do końca ... a szedł trochę. Potem tak mnie coś natchnęło aby spróbować statyczną tablicę + licznik elementów. Efekt - paska postępu nie było widać.

Pozdrawiam

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.