2012-03-31 16 views
8

Jestem ciekawy, czy możliwe jest określenie maksymalnego rozmiaru tablicy w C++.Programowo znajdź maksymalny statyczny rozmiar tablicy w C++

#include <iostream> 

    using namespace std; 

    #define MAX 2000000 

    int main() 
    { 
     long array[MAX]; 
     cout << "Message" << endl; 
     return 0; 
    } 

Kompiluje się dobrze, ale następnie segfaults zaraz po uruchomieniu (nawet jeśli tablica nie jest faktycznie odwoływana). Wiem, że to także rozmiar tablicy, ponieważ jeśli zmienię go na 1000000, działa dobrze.

Czy istnieje jakiś sposób zdefiniowania miejsca lub sposób uzyskania #define MAX MAX_ALLOWED_ARRAY_SIZE_FOR_MY_MACHINE_DEFINED_SOMEWHERE_FOR_ME?

Nie potrzebuję tego do niczego, to pytanie jest ze względu na ciekawość.

+0

chcesz tylko zrozumieć maksymalny rozmiar tablicy w stosie? może rekursja działa dla ciebie? nie w jednej tablicy, ale w połączeniu? – tartar

+2

@tar Co ma zrobić rekursja? –

+0

Ten wpis nie odpowiada na twoje pytanie, ale powinien być interesujący, ponieważ mówi o tym samym problemie z wadą seg: http://stackoverflow.com/questions/851122/large-2d-array-gives-segmentation-fault –

Odpowiedz

10

Nie ma sposobu, aby określić to statycznie, ponieważ rzeczywisty granica zależy od tego, ile miejsca na stosie Twój wątek został podany. Możesz stworzyć nowy wątek, dać mu 10 megabajtów stosu, a będziesz mógł przydzielić odpowiednio większą lokalną tablicę.

Kwota, którą można przydzielić na stosie, zależy również od tego, ile już wykorzystano do tej pory.

+0

To ma sens, myślę, że nie rozumiem zbyt dobrze różnicy między sposobem obsługi tablic statycznych i tablic dynamicznych w zakresie alokacji pamięci w czasie wykonywania – SirGuy

+3

Po zadeklarowaniu zmiennej lokalnej, miejsce dla całej tablicy jest przydzielane z przestrzeń stosu (w przeciwieństwie do niektórych innych języków, takich jak Java). Gdy zadeklarujesz coś globalnego, poza funkcją, linker ustawia adresy pamięci, aby przestrzeń istniała jeszcze przed uruchomieniem programu. Stos ma ograniczony rozmiar (zwykle 1 megabajt na nowoczesnym systemie operacyjnym, ale może się znacznie różnić), podczas gdy dostępna przestrzeń statyczna to cała przestrzeń adresowa aplikacji urządzenia (2 GB lub mniej w systemie 32-bitowym). –

+0

Czy są jakieś różnice w wydajności między tymi dwoma typami pamięci? Również _wszystkie programy używają tej samej przestrzeni statycznej, nawet jeśli nie są uruchomione? Czy jest jakieś udostępnianie, które występuje w przestrzeni statycznej lub jeśli instalujesz programy z milionami, które możesz po prostu zabraknąć? Zgaduję, że problemy z tym nie pojawiają się zbyt często. – SirGuy

4
void foo(int level){ 
int dummy[100]; 
cerr<<level<<endl; 
foo(level+1); 
} 

Następnie, możesz pomnożyć ostatni wydrukowany poziom z 400 bajtami. Wywołania rekursywne zajmują większość przestrzeni stosu, ale możesz uzyskać niższą granicę. Może brak mi jakiegoś zrozumienia zarządzania pamięcią tutaj, tak otwartego na poprawki.

Oto, co otrzymałem na mojej maszynie z różnym rozmiarem matrycy.

level array size stack total 
24257  100  9702800 
2597 1000  10388000 
    260 10000  10400000 
    129 20000  10320000 
    64 40000  10240000 
    25 100000  10000000 
    12 200000  9600000 
+0

Teraz rozumiem, co miałeś na myśli, dziękuję – SirGuy

+0

Grałem z tym rozwiązaniem dla zwiększenia rozmiaru tablicy całkowitej. Tylko w celu wyeliminowania dodatkowego obciążenia wywołanego funkcją na każdym etapie. Maksymalnie mam, gdy rozmiar tablicy wynosi 10000, a maksymalny rozmiar stosu na moim komputerze (ubuntu 10.04) to 10400000 bajtów. – tartar

+0

Strzeż się optymalizacji połączeń ogonowych tutaj. –

1

Proszę przeczytać this, aby zrozumieć ograniczenia, które są ustalane przez sprzęt i kompilator. Nie sądzę, że można zdefiniować MAX, aby od razu go użyć.

2

Większość zmiennych zadeklarowanych w funkcjach jest przydzielanych na the stack, co w zasadzie jest blokiem pamięci o stałym rozmiarze. Próba przydzielenia zmiennej stosu większej niż rozmiar stosu spowoduje, że stack overflow, co jest spowodowane przez segfault.

Często wielkość stosu jest 8MB, więc na komputerze 64-bitowym, long max[1000000] ma rozmiar 8*1000000 < 8MB (stos jest „bezpieczny”), ale long max[2000000] ma rozmiar 8*2000000 > 8MB, więc przepełnienia stosu i naruszenia ochrony pamięci programu.

Z drugiej strony, dynamiczne przydzielanie tablicy przy użyciu malloc powoduje umieszczenie pamięci w the heap, która jest w zasadzie nieograniczona (4 GB na 32-bitowej maszynie, 17 179 886 184 GB na 64-bitowym komputerze).