Problem z wyciekiem pamięci w stosie

Odpowiedz Nowy wątek
2011-10-23 15:14
goffer
0

Mam problem z wyciekiem pamięci w stosie i nie mam pojęcia co robię źle. Pewnie to coś banalnego ale nie potrafię tego znaleźć. Wykonanie programu tak jak poniżej skutkuje zajęciem 300MB pamięci. gcc version 4.6.1

# include <iostream>

using namespace std;

template<typename Typ> 
class StackEl
    {
    public:
    Typ val;
    StackEl <Typ> *prev;
    };

template<typename Typ> 
class Tstack
    {
    public:
    StackEl <Typ> *curr;
    unsigned long int counter;
    Tstack()
        {
        this->counter = 0;
        }
    ~Tstack()
        {
        while(this->counter > 0)
            {
            this->pop();            
            }
        }
    void push(Typ val)
        {
        StackEl <Typ> *next;                /// deklaracja nowego elementu stosu
        next = new StackEl <Typ>;           /// alokacja nowego elementu stosu
        next->val = val;                    /// przypisanie wartości do nowego elementu
        next->prev = curr;                  /// przypisanie do nowego elementu wskażnika na element bieżący
        this->curr = next;                  /// ustawienie nowego elementu jeko element bieżący
        this->counter++;                    /// zwiększenie licznika stosu
        }
    Typ top()
        {
        if(this->counter)
            {
            return this->curr->val;
            }
            else
            {
            throw "ERROR: Stack is empty !!!";
            }
        }
    Typ pop()
        {
        if(this->counter)
            {
            StackEl <Typ> *to_del = curr;   /// deklaracja zmiennej tymczasowej
            Typ tmp = this->curr->val;      /// kopiowanie wartości z góry stosu
            curr = curr->prev;              /// przenoszenie góry stosu o poziom niżej
            delete to_del;                  /// usuwanie poprzedniej góry stosu
            this->counter--;                /// zmniejszanie licznika stosu o jeden
            return tmp;                     /// zwracanie poprzedniej wartości góry stosu
            }
            else
            {
            throw "ERROR: Stack is empty !!!";
            }
        }
    unsigned long int count()
        {
        return counter;
        }
    };

int main()
    {
    Tstack <int> a;
    for(int i = 0; i < 40000000; i++) a.push(i);
    for(int i = 0; i < 40000000; i++) a.pop();
    cin.get();
    } 

Pozostało 580 znaków

2011-10-24 15:17
0

40000000 2 8 = ?
Policzyłeś zera w tej liczbie?
Ja bym powiedział, że przy takich danych te 300 MB to i tak mało.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2011-10-24 15:19

Pozostało 580 znaków

2011-10-24 16:15
0

@MarekR22: coś źle liczysz, 40000000 elementów razy 8 (4 na 32-bitowego inta i 4 na 32-bitowy wskaźnik) daje 320000000 bajtów, czyli akurat 305 z małym hakiem megabajtów (liczonych z potęgą 2^1024).

Zwolnienie stosu przez delete niekoniecznie zwróci pamięć systemowi operacyjnemu, przynajmniej nie od razu - tak że w momencie cin.get proces nadal będzie zajmował 300 MB.

policz czy destruktor jest wywoływany tyle samo razy co konstruktor — dla pewności czy wszystko jest zwalniane — i tak to zostaw.
menedżer pamięci zajmie się resztą.

edytowany 2x, ostatnio: Azarien, 2011-10-24 16:20
Od liczenia jest valgrind, co by się chłopak nie męczył. ;-) - Endrju 2011-10-24 17:19
Ok ślepy nie zauważył różnicy w piętach for :-). Ale i tak trzeba uwzględnić dane na obsługę sterty. - MarekR22 2011-10-24 19:53

Pozostało 580 znaków

2011-10-24 20:47
goffer
0

Dzięki wielki za podpowiedź, sam bym nie wpadł że system zwalnia tą pamięć po jakimś czasie, dotąd zawsze działo się to natychmiastowo. Możecie jeszcze spojrzeć na to. Faktycznie nie ma wycieków ale jest ogromna konsumpcja na stertę. Czy da się z tym cokolwiek zrobić?

==3763== HEAP SUMMARY:
==3763== in use at exit: 74,850,736 bytes in 4,678,171 blocks
==3763== total heap usage: 4,678,171 allocs, 0 frees, 74,850,736 bytes allocated
==3763==
==3763== LEAK SUMMARY:
==3763== definitely lost: 0 bytes in 0 blocks
==3763== indirectly lost: 0 bytes in 0 blocks
==3763== possibly lost: 0 bytes in 0 blocks
==3763== still reachable: 74,850,736 bytes in 4,678,171 blocks
==3763== suppressed: 0 bytes in 0 blocks
==3763== Reachable blocks (those to which a pointer was found) are not shown.
==3763== To see them, rerun with: --leak-check=full --show-reachable=yes
==3763==
==3763== For counts of detected and suppressed errors, rerun with: -v
==3763== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

Pozostało 580 znaków

2011-10-25 08:17
0

To jest optymalizacja od kompilatora, system operacyjny może dostarczyć ram procesowi jedynie w bardzo dużych blokach (o ile pamiętam jest to zwykle 32 kB). Do tego proces przydziału ramu przez system nie jest bardzo szybki, więc standardowe biblioteki odpowiedzialne za zarządzanie pamięcią programu nie oddają od razu pamięci do systemu, bo ta pamięć może się wkrótce przydać.
Po co chcesz ingerować w proces zarządzania pamięcią? Chcesz oszczędzić pamięć, napisz lepszy algorytm.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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