Strona 1 z 1
[C++] Kłopoty z pamięcią
: 07 listopada 2007, 15:38
autor: Smerf
Kod: Zaznacz cały
#include<iostream>
using namespace std;
int main()
{
int tab[1000001];
int tab1[1000001];
int tab2[1000001];
int n;
cin>>n;
}
kompiluje się, ale przy uruchomieniu wywala Naruszenie ochrony pamięci.
Kod: Zaznacz cały
#include<iostream>
using namespace std;
int main()
{
int tab[1000001];
int tab1[1000001];
int tab2[1000001];
int n;
}
kompiluje się i działa
Kod: Zaznacz cały
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> tab(1000001);
vector<int> tab1(1000001);
vector<int> tab2(1000001);
int n;
cin>>n;
}
kompiluje się i działa
Ktoś wie o co chodzi?????
: 07 listopada 2007, 16:27
autor: cepe
Ja chyba wiem: w pierwszym przypadku robisz za dużo zmiennych statycznych! i do tego próbujesz ich używać. W drugim przypadku deklarujesz również za dużo ale ich nie używasz więc nie ma naruszenia pamieci, w trzecim przypadku używasz vector'a , który pamieć przydziela dynamicznie więc wszystko jest w porządku.
Zrób tak, a będzie dobrze:
Kod: Zaznacz cały
#include <iostream>
using namespace std;
int main()
{
int *tab = new int[1000001];
int *tab1 = new int [1000001];
int *tab2 = new int[1000001];
int n;
cin>>n;
...
delete [] tab;
delete [] tab1;
delete [] tab2;
return 0;
}
PS: Niczego nie jestem pewien, jak znajdę dowody (w internecie) tego co mi się wydaje to napiszę.
: 07 listopada 2007, 16:46
autor: ponton
Nie statyczne, tylko automatyczne/lokalne, Paweł.
Te są na stosie. Zmienne dynamiczne (malloc() z C i new z C++, którego używa klasa vector) są tworzone na stercie. Podejrzewam, że po prostu stos się przepełnia (adres n jest poza zakresem stosu i stąd segmentation fault).
: 07 listopada 2007, 16:52
autor: cepe
ponton (Tomek xD): masz rację. Chodziło mi o zmienne automatyczne: te deklarowane lokalnie i globalnie bez przydzielania pamięci za pomocą operatora new. Kiedyś wg google na stos i stertę było przeznaczone 64 KB. Jeśli się to nie zmieniło to tablice zadeklarowane przez Smerfa grubo przekraczają tą liczbę!
: 07 listopada 2007, 17:06
autor: Smerf
Ok, zadeklarowałem na stercie i działa
Jeżeli wyrzuciam tab0 z programu to tab[1] i tab[2] mieszczą się na stosie... Więc mam takie pytanka jeszcze: od czego zależy ile danych może być zadeklarowane na stosie? dane na stercie mogą być deklarowane dopóki starczy RAMu?
: 07 listopada 2007, 17:17
autor: ponton
: 09 listopada 2007, 00:36
autor: phund
Smerf pisze:dane na stercie mogą być deklarowane dopóki starczy RAMu?
Kiedyś z ciekawości napisałem program "pożerający" pamięć - w pętli alokował ciągle nowe zasoby. trudno było stwierdzić, ile zajmował pamięci pod koniec, bo system nieźle zamulił... podejrzewam, że zaczęło się przenoszenie danych na swap, ale nie nadążało to za pętlą. W pewnym momencie program po prostu się zakończył - jeśli się nie mylę, to proces został zabity przez kernel jako mało ważny
a zajmujący całą dostępną pamięć i chcący jeszcze
Więc kiedy osiągniesz kres pamięci, to kernel zacznie zabijać mało ważne według niego procesy w celu odzyskania zasobów dla systemu.
Niech mnie ktoś poprawi, jeśli coś pokręciłem albo podałem nieściśle
: 09 listopada 2007, 00:43
autor: ponton
Z tego co wiem, jest jakiś limit górny też. 4 GB? Przydałby się ktoś, kto wklei odpowiednie linijki ze źródła kernela i udowodni.
: 09 listopada 2007, 22:34
autor: fabix
phund pisze: Więc kiedy osiągniesz kres pamięci, to kernel zacznie zabijać mało ważne według niego procesy w celu odzyskania zasobów dla systemu.
Wcale nie musi tak, być system ogranicza zasoby użytkownika według reguł które można uzyskać tak:
Swoją drogą to warto zabezpieczyć system sensownie jako root. Jeśli widzisz po wydaniu powyższego polecenia unlimited to wypadało by to zmienić. Twój system uodporni się na ataki typu Forkbomb.
Info tutaj
Uważajcie na zbyt małe limity!
A co do stosu to w każdym kompilatorze daje się zmienić jego rozmiar. Czy to przy kompilacji, czy wręcz podczas uruchamiania programów. Dla gcc mamy -mstack-size=rozmiar.