[C++] K

Potrzebujesz pomocy z C, C++, perl, python, itp.
Smerf
Posty: 35
Rejestracja: 15 września 2007, 20:58

[C++] Kłopoty z pamięcią

Post 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?????
cepe
Posty: 31
Rejestracja: 08 czerwca 2007, 19:14
Lokalizacja: Krasnystaw / Wroc³aw

Post 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ę.
ponton
Beginner
Posty: 406
Rejestracja: 24 stycznia 2007, 01:40
Lokalizacja: Kalisz/Wroc³aw

Post 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).
cepe
Posty: 31
Rejestracja: 08 czerwca 2007, 19:14
Lokalizacja: Krasnystaw / Wroc³aw

Post 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ę!
Smerf
Posty: 35
Rejestracja: 15 września 2007, 20:58

Post 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?
ponton
Beginner
Posty: 406
Rejestracja: 24 stycznia 2007, 01:40
Lokalizacja: Kalisz/Wroc³aw

Post autor: ponton »

Dokładnie to nie wiem, ale może to (http://pl.wikipedia.org/wiki/Przepełnienie_stosu) pomoże.
phund
Posty: 58
Rejestracja: 30 marca 2007, 11:33
Lokalizacja: UTP

Post 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 :)
ponton
Beginner
Posty: 406
Rejestracja: 24 stycznia 2007, 01:40
Lokalizacja: Kalisz/Wroc³aw

Post 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. ;)
fabix
Posty: 61
Rejestracja: 26 sierpnia 2006, 13:31

Post 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:

Kod: Zaznacz cały

ulimit -a
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.
ODPOWIEDZ