Problem z wyciekiem pamięci w stosie

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();
    } 
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.

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ą.

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)

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.

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