Mikrobki musze napisac funkcje void stack() ktora bedzie powodowala przepelnienie sie stosu i w momencie gdy do tego dojdzie, program bedzie przerywany, a na ekranie zostanie wypisany stosowny komunikat (wewnatrz programu, nie przez kompilator). Main() ma wypisywac ile razy ta funkcja zostala wywolana, zanim przepelnil sie stos. Pytanie rowniez jest o to jak mozna to przepelnianie przyspieszyc i jak oszacowac na podstawie wynikow wielkosc stosu.
Nie mam pojecia jak sie do tego zabrac, domyslam sie, ze trzeba kombinowac cos z rekurencja. Pomozecie?
@erwit: Odpowiedz z gory, domyslna wielkosc stosu w msvc to 1MiB, w mingw to (chyba) ok 8MiB. Na linuksie jest to ustawienie systemowe.
Tak, rekurencja moƶe Ci przepełnić stos, ale musisz wziąć pod uwagę wielkość ramki, która moƶe się zmieniać w zaleƶności od kompilatora i flag kompilacji. Ponadto przepełnienie stosu wywali Ci program, nie będziesz mógł wypisać komunikatu błędu (przynajmniej nie za pomocą narzędzi dostępnych w standardowym C++, coś system-specific
@Vetinari: Ale tak co najwyƶej sprawdzi głębokość rekurencji. No i ogranicza się do konkretnego systemu. Chociaƶ w sumie samo wspomnienie stosu zamyka go w implementacjach uƶywających stosu (stadnard C++ nie wspomina o takim wynalazku ani słowem).
@erwit: Rozmiar stosu możesz oszacować odejmując wartość wskaźnika do zmiennej funkcji od zmiennej np w main(). Oczywiście to implementation specific, jak całe to zadanie :P
@WolverinePL: @Vetinari: @KrzaQ2: Poczytalem sobie troche o sygnalach w unixie, ktore byly sa dla mnie czyms zupelnie nowym, swietna rzecz. Zaczalem pisac moj program, lecz juz na samym poczatku napotkalem na komplikacje:
#include /* standardowe funkcje UNIXowe, takie jak getpid() /
@erwit: Bo tak funkcja w ogóle nie jest wywoływana, stack overflow jest wcześniej. Poprawne uƶycie signal jest na początku maina, rejestrujesz callback obsługujący dany sygnał. To nie
Okej troche pokombinowalem i wynik jest taki: jezeli wywoluje z maina void kupa(); to dziala, tzn, przechwytuje sygnal, a jezeli f(); to nie przechwytuje.
@erwit: Ciekawe :) Wydaje mi sie, ze wytlumaczenie tego jest dosyc prozaiczne: jako, ze skonczyl sie stos to nie mozna wywolac signal handlera - to w sumie jest zwykla funkcja w userspace z takim samym abi jak wszystko inne :)
- stos w x86 sie dekrementuje jak sie cos wsadza na niego
- jak wolasz funkcje to jest uzywany po ludzku PUSH, czyli przesuwa sie ESP, jak piszesz poza stos (tak jak w kupa()), to po prostu tam piszesz, ESP w dalszym ciagu wskazuje na poprawny obszar stosu
@WolverinePL: >Rozmiar stosu możesz oszacować odejmując wartość wskaźnika do zmiennej funkcji od zmiennej np w main(). Oczywiście to implementation specific, jak całe to zadanie :P
@erwit: Niczego nie przesuwa, po prostu piszesz poza obszar stosu. Abstrakcyjnie to dziala tak: masz sobie jakis fragment pamieci przydzielonej na stos, powiedzmy, ze jest on pomiedzy adresami 100 a 200, potem masz "zmienna", o nazwie ESP i poczatkowo ma ona wartosc 200. Jak wolasz funkcje to wrzucasz rozne rzeczy na stos, tzn:
Nie mam pojecia jak sie do tego zabrac, domyslam sie, ze trzeba kombinowac cos z rekurencja. Pomozecie?
#cpp #programowanie
Tak, rekurencja moƶe Ci przepełnić stos, ale musisz wziąć pod uwagę wielkość ramki, która moƶe się zmieniać w zaleƶności od kompilatora i flag kompilacji. Ponadto przepełnienie stosu wywali Ci program, nie będziesz mógł wypisać komunikatu błędu (przynajmniej nie za pomocą narzędzi dostępnych w standardowym C++, coś system-specific
@Vetinari: ooo, to brzmi dobrze, dzieki wielkie, poczytam i w razie co bede wolal, ok?
#include /* standardowe funkcje UNIXowe, takie jak getpid() /
#include / różne typy
catchod łapania wyjątków.
http://linux.die.net/man/2/signal
kurcze poprawilem wedlug Twoich wskazowek (przynajmniej tak mi sie wydaje), ale dalej nie dziala :(
'#include /* standardowe funkcje UNIXowe, takie jak getpid()
Okej troche pokombinowalem i wynik jest taki: jezeli wywoluje z maina void kupa(); to dziala, tzn, przechwytuje sygnal, a jezeli f(); to nie przechwytuje.
- stos w x86 sie dekrementuje jak sie cos wsadza na niego
- jak wolasz funkcje to jest uzywany po ludzku PUSH, czyli przesuwa sie ESP, jak piszesz poza stos (tak jak w kupa()), to po prostu tam piszesz, ESP w dalszym ciagu wskazuje na poprawny obszar stosu
kupa() jest mi do niczego nie potrzebna, zalezy mi na dzialaniu f();
Wydaje mi sie, ze tylko rekurencja moge rozwiazac to
moglbys przyblizyc jak to ma wygladac?
@erwit: Niczego nie przesuwa, po prostu piszesz poza obszar stosu. Abstrakcyjnie to dziala tak: masz sobie jakis fragment pamieci przydzielonej na stos, powiedzmy, ze jest on pomiedzy adresami 100 a 200, potem masz "zmienna", o nazwie ESP i poczatkowo ma ona wartosc 200. Jak wolasz funkcje to wrzucasz rozne rzeczy na stos, tzn:
- zapisujesz swoja wartosc pod adresem z ESP