Apakah ada panjang maksimum untuk array di C ++?
Apakah ini batas C ++ atau tergantung pada mesin saya? Apakah itu dapat diubah? Apakah itu tergantung pada jenis array terbuat dari apa?
Dapatkah saya melanggar batas itu atau saya harus mencari cara yang lebih baik untuk menyimpan informasi? Dan apa yang seharusnya menjadi cara paling sederhana?
Yang harus saya lakukan adalah menyimpan int lama pada array, saya bekerja di lingkungan Linux. Pertanyaan saya adalah: apa yang harus saya lakukan jika saya perlu menyimpan array bilangan bulat panjang N dengan N> 10 digit?
Saya memerlukan ini karena saya sedang menulis beberapa algoritma kriptografi (seperti misalnya p-Pollard) untuk sekolah, dan menabrak dinding bilangan bulat dan panjang representasi array.
new
ataumalloc
. Potongan memori yang lebih besar dari array dapat diakses melalui pointer.Tidak ada yang menyebutkan batas ukuran bingkai tumpukan .
Ada dua tempat memori dapat dialokasikan:
Batas ukuran di sini adalah kombinasi dari perangkat keras yang tersedia dan kemampuan OS untuk mensimulasikan ruang dengan menggunakan perangkat lain untuk sementara menyimpan data yang tidak digunakan ( yaitu memindahkan halaman ke hard disk).
Batas ukuran di sini ditentukan oleh kompiler (dengan batasan perangkat keras yang memungkinkan). Jika Anda membaca dokumentasi kompiler, Anda sering dapat mengubah ukuran ini.
Jadi, jika Anda mengalokasikan array secara dinamis (batasnya besar dan dijelaskan secara rinci oleh posting lain.
Atau jika array dialokasikan pada stack maka Anda dibatasi oleh ukuran frame stack. Vektor NB dan wadah lain memiliki kehadiran kecil di tumpukan tetapi biasanya sebagian besar data akan berada di tumpukan.
sumber
new
ataumalloc
).Global Arrays
sementara tidak cantik dan terbaik dihindari, ini tidak jatuh di bawah pembatasanstack
, dan Anda tidak perlumalloc
/free
bekerja dengan mereka.Melihatnya dari sudut pandang praktis dan bukan teori, pada sistem Windows 32 bit, jumlah total maksimum memori yang tersedia untuk satu proses adalah 2 GB. Anda dapat mematahkan batasan dengan masuk ke sistem operasi 64 bit dengan lebih banyak memori fisik, tetapi apakah melakukan ini atau mencari alternatif sangat tergantung pada pengguna yang Anda tuju dan anggaran mereka. Anda juga dapat mengembangkannya menggunakan PAE .
Jenis array sangat penting, karena penyelarasan struktur default pada banyak kompiler adalah 8 byte, yang sangat boros jika penggunaan memori menjadi masalah. Jika Anda menggunakan Visual C ++ untuk menargetkan Windows, lihat arahan paket #pragma sebagai cara mengatasi hal ini.
Hal lain yang harus dilakukan adalah melihat apa yang dalam teknik kompresi memori dapat membantu Anda, seperti matriks jarang, kompresi cepat, dll ... Sekali lagi ini sangat tergantung pada aplikasi. Jika Anda mengedit posting Anda untuk memberikan lebih banyak informasi tentang apa yang sebenarnya ada dalam array Anda, Anda mungkin mendapatkan jawaban yang lebih berguna.
Sunting: Diberikan sedikit informasi lebih lanjut tentang persyaratan Anda, kebutuhan penyimpanan Anda tampaknya antara 7,6 GB dan 76 GB tidak terkompresi, yang akan membutuhkan kotak 64 bit yang agak mahal untuk disimpan sebagai larik dalam memori di C ++. Ini menimbulkan pertanyaan mengapa Anda ingin menyimpan data dalam memori, di mana seseorang mengandaikan kecepatan akses, dan untuk memungkinkan akses acak. Cara terbaik untuk menyimpan data ini di luar array cukup banyak berdasarkan pada bagaimana Anda ingin mengaksesnya. Jika Anda perlu mengakses anggota array secara acak, untuk sebagian besar aplikasi cenderung ada cara pengelompokan rumpun data yang cenderung diakses pada saat yang sama. Misalnya, dalam database GIS dan spasial yang besar, data sering kali dibuat berdasarkan wilayah geografis. Dalam istilah pemrograman C ++, Anda dapat mengganti operator array [] untuk mengambil bagian data Anda dari penyimpanan eksternal sebagaimana diperlukan.
sumber
Saya setuju dengan hal di atas, bahwa jika Anda menginternalisasi array Anda dengan
maka SIZE dibatasi oleh ukuran bilangan bulat. Tetapi Anda selalu dapat malloc sepotong memori dan memiliki pointer ke sana, sebesar yang Anda inginkan selama malloc tidak mengembalikan NULL.
sumber
int oops[INT_MAX]{0};
Menghasilkan,C2148 - total size of array must not exceed 0x7fffffff bytes
66%
memori yang saat ini digunakan sebelum meluncurkan aplikasi saya sebagai debug pada Windows 10 dengan VS2017, saya memiliki batas yang tidak ditentukan pada seberapa besar int-array yang dapat saya inisialisasi0
. Kadang-kadang saya bisa melakukannya dengan elemen ~ 257k, kadang-kadang saya mendapatkan stack overflow. Jika saya menambahkan sesuatu ke aplikasi saya selain main dan array, angka itu turun (jelas). Saya harus bereksperimen untuk menentukan angka ini, jadi saya tidak melihat bagaimana metrik ini dapat diandalkan selain mengetahui batas teoritis Anda dalam ruang hampa.Untuk meringkas tanggapan, luaskan, dan untuk menjawab pertanyaan Anda secara langsung:
Tidak, C ++ tidak memberlakukan batasan apa pun untuk dimensi array.
Tetapi karena array harus disimpan di suatu tempat dalam memori, maka batas terkait memori yang dikenakan oleh bagian lain dari sistem komputer berlaku. Perhatikan bahwa batas-batas ini tidak secara langsung berhubungan dengan dimensi (= jumlah elemen) dari array, tetapi lebih kepada ukurannya (= jumlah memori yang diambil). Dimensi ( D ) dan ukuran dalam memori ( S ) dari array tidak sama, karena mereka terkait oleh memori yang diambil oleh elemen tunggal ( E ): S = D * E . SekarangE
tergantung pada:
'ruang terbuang' (padding) antara elemen
Perhatikan juga bahwa Anda biasanya mendapatkan batasan terkait memori yang berbeda dengan mengalokasikan data array pada stack (sebagai variabel otomatis:)
int t[N]
, atau di heap (alokasi dinamis denganmalloc()
/new
atau menggunakan mekanisme STL), atau di bagian statis dari memori proses (seperti variabel statis:)static int t[N]
. Bahkan ketika mengalokasikan pada heap, Anda masih membutuhkan sejumlah kecil memori pada stack untuk menyimpan referensi ke blok memori yang dialokasikan heap (tetapi biasanya diabaikan).Ukuran
size_t
tipe tidak memiliki pengaruh pada programmer (saya berasumsi programmer menggunakansize_t
tipe untuk pengindeksan, seperti yang dirancang untuk itu), karena penyedia kompiler harus ketypedef
tipe integer yang cukup besar untuk mengatasi jumlah memori maksimal yang mungkin untuk platform yang diberikan Arsitektur.Sumber keterbatasan ukuran memori berasal dari
Mereka tidak dapat 'tweak' pada tingkat aplikasi, tetapi Anda bebas untuk menggunakan kompiler yang berbeda (untuk mengubah batas ukuran tumpukan), atau port aplikasi Anda ke 64-bit, atau port ke OS lain, atau ubah fisik / konfigurasi memori virtual dari mesin (virtual? fisik?).
Ini tidak biasa (dan bahkan disarankan) untuk memperlakukan semua faktor di atas sebagai gangguan eksternal dan dengan demikian sebagai sumber kesalahan runtime yang mungkin terjadi, dan untuk secara hati-hati memeriksa & bereaksi terhadap kesalahan terkait alokasi memori dalam kode program Anda.
Jadi akhirnya: sementara C ++ tidak memaksakan batasan apa pun, Anda masih harus memeriksa kondisi terkait memori yang merugikan saat menjalankan kode Anda ... :-)
sumber
Seperti banyak jawaban bagus yang dicatat, ada banyak batasan yang bergantung pada versi kompiler C ++, sistem operasi dan karakteristik komputer Anda. Namun, saya menyarankan skrip berikut pada Python yang memeriksa batas pada mesin Anda.
Ini menggunakan pencarian biner dan pada setiap iterasi memeriksa apakah ukuran menengah dimungkinkan dengan membuat kode yang mencoba membuat array ukuran. Skrip mencoba mengompilasinya (maaf, bagian ini hanya berfungsi di Linux) dan menyesuaikan pencarian biner tergantung pada keberhasilannya. Saksikan berikut ini:
Anda dapat menyimpannya di mesin Anda dan meluncurkannya, dan itu akan mencetak ukuran maksimum yang dapat Anda buat. Untuk mesin saya adalah 2305843009213693951.
sumber
Satu hal yang menurut saya tidak disebutkan dalam jawaban sebelumnya.
Saya selalu merasakan "bau busuk" dalam arti refactoring ketika orang menggunakan hal-hal seperti itu dalam desain mereka.
Itu adalah array yang sangat besar dan mungkin bukan cara terbaik untuk merepresentasikan data Anda baik dari sudut pandang efisiensi maupun dari sudut pandang kinerja.
Bersulang,
rampok
sumber
Jika Anda harus berurusan dengan data sebesar itu, Anda harus membaginya menjadi beberapa bagian yang dapat dikelola. Itu tidak akan masuk ke memori di komputer kecil mana pun. Anda mungkin dapat memuat sebagian data dari disk (apa pun yang cukup masuk akal), melakukan perhitungan dan mengubahnya, menyimpannya ke disk, lalu ulangi hingga selesai.
sumber
Menjengkelkan tidak spesifik seperti semua jawaban saat ini, mereka sebagian besar benar tetapi dengan banyak peringatan, tidak selalu disebutkan. Intinya adalah, Anda memiliki dua batas atas, dan hanya satu yang benar-benar didefinisikan, jadi YMMV :
1. Batas waktu kompilasi
Pada dasarnya, apa yang akan diizinkan oleh kompiler Anda. Untuk Visual C ++ 2017 pada kotak Windows 10 x64, ini adalah batas maksimal saya pada waktu kompilasi sebelum mencapai batas 2GB,
Jika saya melakukan ini sebagai gantinya,
Saya akan mendapatkan:
Saya tidak yakin bagaimana 2G terkoreksi ke
255999996
/7
. Saya mencari-cari kedua nomor di Google, dan satu-satunya hal yang dapat saya temukan yang mungkin terkait adalah * T&J ini tentang masalah presisi dengandc
. Apa pun itu, tampaknya bukan masalah jenis int array mana yang Anda coba isi, berapa banyak elemen yang dapat dialokasikan.2. Batas waktu berjalan
Tumpukan dan tumpukan Anda memiliki batasannya sendiri. Batasan ini adalah nilai yang berubah berdasarkan sumber daya sistem yang tersedia, serta seberapa "berat" aplikasi Anda. Misalnya, dengan sumber daya sistem saya saat ini, saya bisa menjalankannya:
Tetapi jika saya mengubah sedikit saja ...
Bam! Stack overflow!
Dan untuk merinci seluruh titik aplikasi Anda, ini bagus untuk dilakukan:
Tapi ini menyebabkan stack overflow:
sumber
Saya terkejut fungsi anggota max_size () dari std :: vector belum disebutkan di sini.
Kita tahu bahwa
std::vector
diimplementasikan sebagai array dinamis di bawah kap, jadimax_size()
harus memberikan perkiraan yang sangat dekat dari panjang maksimum dinamis array pada mesin Anda.Program berikut membuat tabel perkiraan panjang array maksimum untuk berbagai tipe data.
Di macOS saya (dentang versi 5.0.1), saya mendapatkan yang berikut:
Pada ideone gcc 8.3 saya mendapatkan:
Perlu dicatat bahwa ini adalah batas teoretis dan pada kebanyakan komputer, Anda akan kehabisan memori jauh sebelum Anda mencapai batas ini. Misalnya, kita melihat bahwa untuk tipe
char
aktifgcc
, jumlah maksimum elemen sama dengan maksstd::size_t
. Mencoba ini , kami mendapatkan kesalahan:Terakhir, seperti yang ditunjukkan oleh @MartinYork, untuk array statis ukuran maksimum dibatasi oleh ukuran tumpukan Anda.
sumber
Seperti yang telah ditunjukkan, ukuran array dibatasi oleh perangkat keras dan OS Anda (man ulimit). Perangkat lunak Anda, mungkin hanya dibatasi oleh kreativitas Anda. Misalnya, dapatkah Anda menyimpan "array" di disk? Apakah Anda benar-benar membutuhkan int panjang panjang? Apakah Anda benar-benar membutuhkan array yang padat? Apakah Anda bahkan memerlukan array sama sekali?
Salah satu solusi sederhana adalah menggunakan Linux 64 bit. Bahkan jika Anda secara fisik tidak memiliki ram yang cukup untuk array Anda, OS akan memungkinkan Anda untuk mengalokasikan memori seolah-olah Anda melakukannya karena memori virtual yang tersedia untuk proses Anda cenderung jauh lebih besar daripada memori fisik. Jika Anda benar-benar perlu mengakses semua yang ada di array, ini berarti menyimpannya di disk. Tergantung pada pola akses Anda, mungkin ada cara yang lebih efisien untuk melakukan ini (yaitu: menggunakan mmap (), atau hanya menyimpan data secara berurutan dalam file (dalam hal ini cukup Linux 32 bit sudah mencukupi)).
sumber
saya akan berkeliling dengan membuat array dinamis 2d:
lebih lanjut tentang ini di sini https://stackoverflow.com/a/936702/3517001
sumber