Kesalahan segmentasi pada ukuran array besar

116

Kode berikut memberi saya kesalahan segmentasi ketika dijalankan pada mesin 2Gb, tetapi bekerja pada mesin 4GB.

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

Ukuran array hanya 4Mb. Apakah ada batasan ukuran array yang bisa digunakan di c ++?

Mayank
sumber

Jawaban:

130

Anda mungkin baru saja mendapatkan tumpukan melimpah di sini. Array terlalu besar untuk muat dalam ruang alamat stack program Anda.

Jika Anda mengalokasikan array pada heap, Anda akan baik-baik saja, dengan asumsi mesin Anda memiliki cukup memori.

int* array = new int[1000000];

Tapi ingat bahwa ini akan meminta Anda ke delete[]array. Solusi yang lebih baik adalah menggunakan std::vector<int>dan mengubah ukurannya menjadi 1000000 elemen.

Charles Salvia
sumber
3
Terima kasih atas jawabannya, tetapi dapatkah Anda menjelaskan kepada saya mengapa array dialokasikan di stack dan mengapa tidak di memori program utama.
Mayank
18
Kode yang diberikan dialokasikan pada tumpukan karena ditentukan sebagai larik dengan jumlah elemen yang konstan pada waktu kompilasi. Nilai hanya diletakkan di heap dengan malloc, baru, dll.
Seth Johnson
6
Semua variabel otomatis dialokasikan di tumpukan. Jika Anda melihat disasseble, Anda akan melihat ukuran variabel lokal Anda dikurangkan dari penunjuk tumpukan. Ketika Anda memanggil malloc atau calloc atau salah satu fungsi memori, fungsinya pergi dan menemukan blok memori yang cukup besar untuk memenuhi permintaan Anda.
Tayangkan ulang
@ Charles mengapa kita dapat mengalokasikan lebih banyak memori dari heap, bukan dari stack? dari pemahaman saya, baik stack dan heap bergerak berlawanan arah dalam ruang alamat yang dialokasikan dalam memori.
saurabh agarwal
2
@saurabhagarwal Heap tidak bergerak. Ini bahkan bukan wilayah memori yang berdekatan. Pengalokasi hanya mengembalikan blok memori bebas yang sesuai dengan kebutuhan ukuran Anda Apa dan di mana tumpukan dan heap?
phuclv
56

Dalam C atau C ++ objek lokal biasanya dialokasikan di stack. Anda mengalokasikan array besar pada tumpukan, lebih dari yang bisa ditangani tumpukan, sehingga Anda mendapatkan aliran tumpukan .

Jangan mengalokasikannya secara lokal di stack, gunakan tempat lain sebagai gantinya. Ini dapat dicapai dengan membuat objek menjadi global atau mengalokasikannya di heap global . Variabel global baik-baik saja, jika Anda tidak menggunakan dari unit kompilasi lain. Untuk memastikan ini tidak terjadi secara tidak sengaja, tambahkan penentu penyimpanan statis, jika tidak, gunakan saja heap.

Ini akan mengalokasikan di segmen BSS, yang merupakan bagian dari heap:

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

Ini akan dialokasikan di segmen DATA, yang merupakan bagian dari heap juga:

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

Ini akan mengalokasikan di beberapa lokasi yang tidak ditentukan di heap:

int main()
{
   int* c = new int[1000000];
   cout << "done\n";
   return 0;
}
Gunther Piez
sumber
Jika Anda menggunakan pola ketiga, mengalokasikan pada heap, jangan lupa untuk menghapus [] penunjuk pada beberapa tahap atau Anda akan membocorkan memori. Atau lihat petunjuk cerdas.
davidA
8
@meowsqueak Tentu saja ini adalah praktik yang baik di deletemana pun Anda mengalokasikan new. Tetapi jika Anda yakin Anda mengalokasikan memori hanya sekali (seperti di main) itu sama sekali tidak diperlukan - memori dijamin akan dibebaskan saat keluar dari main bahkan tanpa eksplisit delete.
Gunther Piez
'at'drhirsch (bagaimana Anda melakukan karakter-at?) - ya, komentar yang adil. Karena OP tampak baru dalam bahasa tersebut, saya hanya ingin memastikan bahwa mereka, dan siapa pun yang melihat jawaban Anda yang bagus, mengetahui implikasi dari opsi ketiga jika digunakan secara umum.
davidA
15

Selain itu, jika Anda menjalankan sebagian besar sistem UNIX & Linux, Anda dapat meningkatkan ukuran tumpukan untuk sementara dengan perintah berikut:

ulimit -s unlimited

Tetapi hati-hati, ingatan adalah sumber daya yang terbatas dan dengan kekuatan besar datanglah tanggung jawab yang besar :)

RSFalcon7
sumber
1
Ini adalah solusinya tetapi saya menyarankan semua untuk sangat berhati-hati saat menghapus batas default ini pada ukuran tumpukan program. Anda tidak hanya akan mengalami penurunan kinerja yang parah tetapi sistem Anda mungkin macet. Misalnya saya mencoba mengurutkan array dengan 16.000.000 elemen integer dengan quicksort pada mesin dengan RAM 4GB dan sistem saya hampir mati. LOL
rbaleksandar
@rbaleksandar Saya pikir Anda ~ Program 16MB hampir mematikan mesin Anda karena Anda bekerja dengan beberapa salinan larik (mungkin satu per panggilan fungsi?) coba implementasi yang lebih sadar memori;)
RSFalcon7
Saya cukup yakin penanganan array baik-baik saja karena saya melewati referensi dan bukan nilai. Hal yang sama terjadi dengan bubbleort. Sial, bahkan jika penerapan quicksort sucks bubbleort saya adalah sesuatu yang tidak mungkin Anda terapkan secara tidak benar. LOL
rbaleksandar
LOL Anda dapat mencoba radix sort, atau cukup gunakan std :: sort :)
RSFalcon7
1
Tidak ada kesempatan. Ini tugas lab. : D
rbaleksandar
3

Array Anda sedang dialokasikan pada tumpukan dalam hal ini mencoba untuk mengalokasikan array dengan ukuran yang sama menggunakan alokasikan.

memutarkan lagi
sumber
3

Karena Anda menyimpan array di stack. Anda harus menyimpannya di heap. Lihat tautan ini untuk memahami konsep heap dan tumpukan.

Narek
sumber