Büyük dizi boyutlarında segmentasyon hatası


116

Aşağıdaki kod, 2Gb'lik bir makinede çalıştırıldığında bana bir segmentasyon hatası veriyor, ancak 4GB'lık bir makinede çalışıyor.

int main()
{
   int c[1000000];
   cout << "done\n";
   return 0;
}

Dizinin boyutu sadece 4Mb'dir. C ++ 'da kullanılabilen bir dizinin boyutuyla ilgili bir sınır var mı?

Yanıtlar:


130

Muhtemelen burada sadece bir yığın taşması yaşıyorsunuz. Dizi, programınızın yığın adres alanına sığamayacak kadar büyük.

Diziyi öbek üzerinde ayırırsanız, makinenizin yeterli belleğe sahip olduğunu varsayarak iyi olmalısınız.

int* array = new int[1000000];

Ancak delete[]bunun diziye girmenizi gerektireceğini unutmayın . Daha iyi bir çözüm kullanmak std::vector<int>ve 1000000 öğeye yeniden boyutlandırmak olacaktır.


3
Cevabınız için teşekkürler, ama dizilerin neden yığında ve neden ana program belleğinde ayrılmadığını bana açıklar mısınız?
Mayank

18
Verilen kod, derleme zamanında sabit sayıda öğeye sahip bir dizi olarak belirtildiğinden yığın üzerinde tahsis eder. Değerler yalnızca malloc, new vb. İle yığına yazılır.
Seth Johnson

6
Tüm otomatik değişkenler yığın üzerinde tahsis edilir. Ayrılabilirliğe bakarsanız, yerel değişkenlerinizin boyutunun yığın işaretçisinden çıkarıldığını göreceksiniz. Malloc veya calloc veya herhangi bir hafıza fonksiyonunu aradığınızda, fonksiyonlar gider ve isteğinizi karşılayacak kadar büyük hafıza blokları bulur.
yeniden

@Charles neden yığından değil, yığından daha fazla bellek ayırabiliyoruz? benim anlayışıma göre, hem yığın hem de yığın bellekte ayrılmış adres alanında ters yönde hareket eder.
saurabh agarwal

2
@saurabhagarwal Yığın hareket etmiyor. Bitişik bir hafıza bölgesi bile değil. Ayırıcı, boyut gereksiniminize uyan boş bir bellek bloğu döndürür Yığın ve yığın nedir ve nerede?
phuclv

56

C veya C ++ 'da yerel nesneler genellikle yığın üzerinde tahsis edilir. Yığın üzerinde yığının kaldırabileceğinden daha büyük bir dizi ayırıyorsunuz, böylece bir yığın akışı elde ediyorsunuz .

Yığın üzerinde yerel olarak ayırmayın, bunun yerine başka bir yer kullanın. Bu, nesneyi global yaparak veya global öbek üzerinde tahsis ederek elde edilebilir . Başka bir derleme biriminden kullanmıyorsanız, global değişkenler iyidir. Bunun kazara meydana gelmediğinden emin olmak için, bir statik depolama tanımlayıcısı ekleyin, aksi takdirde yalnızca yığını kullanın.

Bu, yığının bir parçası olan BSS segmentinde tahsis edilecektir:

static int c[1000000];
int main()
{
   cout << "done\n";
   return 0;
}

Bu, aynı zamanda yığının bir parçası olan DATA segmentinde tahsis edilecektir:

int c[1000000] = {};
int main()
{
   cout << "done\n";
   return 0;
}

Bu, yığın içinde belirtilmemiş bir konuma tahsis edecektir:

int main()
{
   int* c = new int[1000000];
   cout << "done\n";
   return 0;
}

Yığın üzerine tahsis eden üçüncü modeli kullanırsanız, bir aşamada işaretçiyi [] silmeyi unutmayın, yoksa bellek sızdırırsınız. Veya akıllı işaretleyicilere bakın.
Davida

8
@meowsqueak Elbette, deleteayırdığınız her yer için iyi bir uygulama new. Ancak belleği yalnızca bir kez ayırdığınızdan eminseniz (temelde olduğu gibi) kesinlikle gerekli değildir - belleğin açık olmasa bile ana çıkışta serbest bırakılması garanti edilir delete.
Gunther Piez

'at'drhirsch (yine de bir karakteri nasıl yaparsınız?) - evet, adil yorum. OP, dilde yeni göründüğünden, onların ve sizin iyi cevabınızı gören herkesin, genel olarak kullanıldığında üçüncü seçeneğin sonuçlarının farkında olduğundan emin olmak istedim.
Davida

15

Ayrıca, çoğu UNIX ve Linux sisteminde çalışıyorsanız, aşağıdaki komutu kullanarak yığın boyutunu geçici olarak artırabilirsiniz:

ulimit -s unlimited

Ancak dikkatli olun, hafıza sınırlı bir kaynaktır ve büyük bir güç büyük sorumluluklar getirir :)


1
Çözüm budur, ancak programın yığın boyutundaki bu varsayılan sınırları kaldırırken herkese son derece dikkatli olmalarını öneririm. Sadece ciddi bir performans düşüşü yaşamayacaksınız, aynı zamanda sisteminiz çökebilir. Örneğin 16.000.000 tamsayı elemanlı bir diziyi 4GB RAM'li bir makinede quicksort ile sıralamayı denedim ve sistemim neredeyse ölüyordu. LOL
rbaleksandar

@rbaleksandar ~ 16MB'lik bir programın neredeyse makinenizi öldüreceğini düşünüyorum çünkü dizinin birkaç kopyasıyla çalışıyordunuz (işlev çağrısı başına bir tane olabilir mi?) daha fazla belleğe duyarlı bir uygulama deneyin;)
RSFalcon7

Değere göre değil, referansa göre geçtiğim için dizi işlemenin iyi olduğuna eminim. Aynı şey baloncuklar için de geçerlidir. Cehennem, benim Quicksort uygulamam bubbleort'u berbat etse bile muhtemelen yanlış uygulayamayacağın bir şey. LOL
rbaleksandar

LOL radix
sort'ı

1
Şans yok. Bu bir laboratuvar ödevi. : D
rbaleksandar

3

Diziniz yığın üzerinde tahsis ediliyor bu durumda, ayırmayı kullanarak aynı boyutta bir dizi ayırmaya çalışın.


3

Çünkü diziyi yığında depoluyorsunuz. Yığın içinde saklamalısın. Yığın ve yığın kavramını anlamak için bu bağlantıya bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.