C ++에서 배열의 최대 길이가 있습니까?
그것은 C ++ 제한입니까, 아니면 내 컴퓨터에 의존합니까? 조정할 수 있습니까? 배열의 유형에 따라 달라 집니까?
어떻게 든 그 한계를 깨뜨릴 수 있습니까? 아니면 정보를 저장하는 더 좋은 방법을 찾아야합니까? 그리고 가장 간단한 방법은 무엇입니까?
내가해야 할 일은 배열에 long int를 저장하는 것입니다 .Linux 환경에서 일하고 있습니다. 내 질문은 : N> 10 자리수의 N long long 정수 배열을 저장 해야하는 경우 어떻게해야합니까?
학교를 위해 암호화 알고리즘 (예 : p-Pollard와 같은)을 작성하고 있기 때문에 정수가 필요합니다.
답변
C ++가 아니라 하드웨어에 의해 적용되는 두 가지 제한이 있습니다.
첫 번째 한계 (도달해서는 안 됨)는 배열의 인덱스를 설명하는 데 사용되는 크기 유형 (및 크기)의 제한에 의해 설정됩니다. 시스템이 std::size_t
취할 수 있는 최대 값으로 제공됩니다 . 이 데이터 유형은 객체의 크기를 바이트 단위로 포함하기에 충분히 큽니다.
다른 한계는 실제 메모리 한계입니다. 배열의 객체가 클수록 메모리가 가득 차서이 제한에 더 빨리 도달합니다. 예를 들어, vector<int>
주어진 크기 n 의 a 는 일반적으로보다 큼 vector<char>
때문에 유형의 배열 (작은 상수 값 빼기) 보다 몇 배나 많은 메모리를 필요로합니다 . 따라서 a 에는 이전 메모리가 가득 찼을 때보 다 많은 항목이 포함될 수 있습니다 . 원시 C 스타일 배열 같은 수는 좋아 하고 .int
char
vector<char>
vector<int>
int[]
char[]
또한이 상한 은 원하는 방식으로 메모리를 자유롭게 관리 할 수 있기 때문에 allocator
구성하는 데 사용되는 유형에 따라 영향을받을 수 있습니다 . 매우 이상하지만 생각할 수없는 할당자는 객체의 동일한 인스턴스가 리소스를 공유하는 방식으로 메모리를 풀링 할 수 있습니다. 이렇게하면 사용 가능한 모든 메모리를 모두 사용하는 컨테이너에 동일한 객체를 많이 삽입 할 수 있습니다.vector
allocator
그 외에도 C ++은 제한을 두지 않습니다.
답변
아무도 스택 프레임 의 크기에 대한 제한을 언급하지 않았습니다 .
메모리를 할당 할 수있는 두 곳이 있습니다.
- 힙에서 (동적으로 할당 된 메모리)
여기에서 크기 제한은 사용 가능한 하드웨어와 다른 장치를 사용하여 사용하지 않는 데이터를 임시로 저장 ( 즉, 페이지를 하드 디스크로 이동) 하여 공간을 시뮬레이션하는 OS 기능의 조합입니다 . - 스택에서 (로컬로 선언 된 변수).
여기서 크기 제한은 가능한 하드웨어 제한과 함께 컴파일러 정의입니다. 컴파일러 문서를 읽으면 종종이 크기를 조정할 수 있습니다.
따라서 배열을 동적으로 할당하는 경우 (한도가 커서 다른 게시물에 의해 자세히 설명됩니다.
int* a1 = new int[SIZE]; // SIZE limited only by OS/Hardware
또는 배열이 스택에 할당 된 경우 스택 프레임의 크기에 의해 제한됩니다. NB 벡터 및 기타 컨테이너는 스택에 존재하지 않지만 일반적으로 대량의 데이터가 힙에 있습니다.
int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame
답변
32 비트 Windows 시스템에서 이론적 인 관점이 아니라 실용적인 관점에서 보면 단일 프로세스에 사용 가능한 최대 총 메모리 양은 2GB입니다. 훨씬 더 많은 실제 메모리가있는 64 비트 운영 체제로 이동하면 한계를 극복 할 수 있지만이를 수행할지 아니면 대안을 찾을 지 여부는 의도 한 사용자와 예산에 따라 크게 달라집니다. PAE를 사용하여 다소 확장 할 수도 있습니다 .
많은 컴파일러에서 기본 구조 정렬이 8 바이트이므로 배열의 유형은 매우 중요합니다. 이는 메모리 사용에 문제가있는 경우 매우 낭비입니다. Visual C ++를 사용하여 Windows를 대상 으로하는 경우이를 극복하는 방법으로 #pragma pack 지시문을 확인하십시오 .
또 다른 방법은 희소 행렬, 즉석 압축 등 메모리 압축 기술에서 어떤 점이 도움이 될 수 있는지 살펴 보는 것입니다. 다시 말하지만 이는 응용 프로그램에 따라 크게 달라집니다. 실제로 배열에 무엇이 있는지에 대한 정보를 더 제공하기 위해 게시물을 편집하면 더 유용한 답변을 얻을 수 있습니다.
편집 : 정확한 요구 사항에 대한 자세한 정보가 제공되면 스토리지는 압축되지 않은 7.6GB와 76GB 사이 인 것으로 보이며 C ++의 메모리에 배열로 저장하려면 다소 비싼 64 비트 상자가 필요합니다. 액세스 속도를 고려하고 임의 액세스를 허용하는 메모리에 데이터를 저장하려는 이유는 무엇입니까? 이 데이터를 배열 외부에 저장하는 가장 좋은 방법은 액세스 방법에 따라 다릅니다. 배열 구성원에 무작위로 액세스해야하는 경우 대부분의 응용 프로그램에서 동시에 액세스되는 경향이있는 데이터 덩어리를 그룹화하는 방법이 있습니다. 예를 들어, 대규모 GIS 및 공간 데이터베이스에서 데이터는 종종 지리적 영역별로 타일링됩니다. C ++ 프로그래밍 용어에서는 필요에 따라 [] 배열 연산자를 재정 의하여 외부 저장소에서 데이터의 일부를 가져올 수 있습니다.
답변
위의 내용에 동의합니다. 배열을 초기화하는 경우
int myArray[SIZE]
그런 다음 SIZE는 정수 크기에 의해 제한됩니다. 그러나 malloc이 NULL을 반환하지 않는 한 원하는만큼 큰 메모리 청크를 malloc하고 그에 대한 포인터를 가질 수 있습니다.
답변
응답을 요약하고, 확장하고, 질문에 직접 대답하기 위해 :
C ++은 배열 의 차원 에 제한을 두지 않습니다 .
그러나 어레이를 메모리 어딘가에 저장해야하므로 컴퓨터 시스템의 다른 부분에 의해 부과 된 메모리 관련 제한이 적용됩니다. 이러한 제한에 직접 관련되지 않는다는 것을주의 차원 배열 (= 요소의 수)가 아니라 그것으로 크기 (= 메모리의 양이 촬영). 치수 ( D ) 및 메모리 크기 ( S 들이 단일 요소 (촬영하여 메모리에 관련된으로 배열)이 동일하지 않은 E ) S = D * E .
지금E 는 다음에 의존합니다.
- 배열 요소의 유형 (요소는 더 작거나 더 클 수 있음)
- 메모리 정렬 (성능을 높이기 위해 요소는 일부 값의 배수 인 주소에 배치되며
요소 사이에 ‘공간 낭비'(패딩)이 발생 함) - 객체의 정적 부분의 크기 (객체 지향 프로그래밍에서 동일한 유형의 객체의 정적 구성 요소는 동일한 유형의 객체 수에 관계없이 한 번만 저장 됨)
: 또한 주 일반적 (자동 변수로 스택에 배열 된 데이터를 할당하여 서로 다른 메모리 관련 제한을 얻을 int t[N]
또는 힙 (와 동적 alocation) malloc()
/ new
(AS 또는 STL 메커니즘을 이용하여), 또는 프로세스 메모리의 정적 부분 정적 변수 🙂 static int t[N]
. 힙에 할당 할 때에도 힙 할당 메모리 블록에 대한 참조를 저장하려면 스택에 약간의 메모리가 필요합니다 (그러나 일반적으로 무시할 수 있습니다). 컴파일러의 프로 바이더는 주어진 플랫폼에서 가능한 최대 메모리 양을 처리 할 수있을 정도로 큰 정수 타입 이어야 하므로 타입
의 크기는 size_t
프로그래머에게 영향을 미치지 않습니다 (프로그래머가 size_t
의도 한대로 인덱싱에 타입을 사용한다고 가정 ) typedef
건축물.
메모리 크기 제한의 원인은 다음과 같습니다.
- 프로세스에 사용 가능한 메모리 양 (64 비트 OS 커널에서도 32 비트 응용 프로그램의 경우 2 ^ 32 바이트로 제한됨)
- 프로세스 메모리의 분할 (예 : 스택 또는 힙을 위해 설계된 프로세스 메모리의 양)
- 물리 메모리의 조각화
- 실제 메모리 양
- 그리고 가상 메모리의 양.
응용 프로그램 수준에서 ‘조정’할 수는 없지만 다른 컴파일러를 사용하거나 (스택 크기 제한을 변경하기 위해) 응용 프로그램을 64 비트로 이식하거나 다른 OS로 이식하거나 물리적 / (가상? 실제?) 머신의 가상 메모리 구성.
위의 모든 요소를 외부 장애로 인해 런타임 오류의 원인으로 취급하고 프로그램 코드에서 메모리 할당 관련 오류를주의 깊게 확인 및 대응하는 것은 드문 일이 아니며 권장되지도 않습니다.
그래서 마지막으로 : C ++은 어떤 제한도 부과하지 않지만 코드를 실행할 때 여전히 메모리와 관련된 불리한 조건을 확인해야합니다 … 🙂
답변
많은 훌륭한 답변이 언급했듯이 C ++ 컴파일러 버전, 운영 체제 및 컴퓨터 특성에 따라 많은 제한이 있습니다. 그러나 파이썬에서 컴퓨터의 한계를 확인하는 다음 스크립트를 제안합니다.
이진 검색을 사용하고 각 반복에서 크기의 배열을 작성하는 코드를 작성하여 중간 크기가 가능한지 확인합니다. 스크립트는이를 컴파일 (미안하지만이 부분은 Linux에서만 작동 함)하고 성공에 따라 이진 검색을 조정하려고합니다. 확인 해봐:
import os
cpp_source = 'int a[{}]; int main() {{ return 0; }}'
def check_if_array_size_compiles(size):
# Write to file 1.cpp
f = open(name='1.cpp', mode='w')
f.write(cpp_source.format(m))
f.close()
# Attempt to compile
os.system('g++ 1.cpp 2> errors')
# Read the errors files
errors = open('errors', 'r').read()
# Return if there is no errors
return len(errors) == 0
# Make a binary search. Try to create array with size m and
# adjust the r and l border depending on wheather we succeeded
# or not
l = 0
r = 10 ** 50
while r - l > 1:
m = (r + l) // 2
if check_if_array_size_compiles(m):
l = m
else:
r = m
answer = l + check_if_array_size_compiles(r)
print '{} is the maximum avaliable length'.format(answer)
컴퓨터에 저장 한 다음 실행할 수 있으며 생성 할 수있는 최대 크기를 인쇄합니다. 내 컴퓨터의 경우 2305843009213693951입니다.
답변
내가 생각하지 않은 한 가지는 이전 답변에서 언급되었습니다.
나는 사람들이 디자인에 그런 것들을 사용할 때 리팩토링 의미에서 항상 “나쁜 냄새”를 감지하고 있습니다.
이는 효율성 측면과 성능 관점 모두에서 데이터를 표현하는 가장 좋은 방법은 아니며 거대한 배열입니다.
건배,
롭