대형 어레이 크기의 세분화 오류


116

다음 코드는 2Gb 시스템에서 실행될 때 분할 오류를 제공하지만 4GB 시스템에서 작동합니다.

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

어레이의 크기는 4Mb에 불과합니다. C ++에서 사용할 수있는 배열의 크기에 제한이 있습니까?

답변:


130

여기에 스택 오버플로가 발생했을 것입니다. 배열이 너무 커서 프로그램의 스택 주소 공간에 맞지 않습니다.

힙에 배열을 할당하면 컴퓨터에 충분한 메모리가 있다고 가정하면 문제가 없습니다.

int* array = new int[1000000];

그러나 이렇게 delete[]하려면 배열 이 필요하다는 것을 기억하십시오 . 더 나은 해결책은 std::vector<int>1000000 요소 를 사용 하고 크기를 조정하는 것입니다.


3
답변 주셔서 감사합니다. 배열이 스택에 할당 된 이유와 주 프로그램 메모리에 할당되지 않은 이유를 설명해 주시겠습니까?
Mayank

18
주어진 코드는 컴파일 타임에 일정한 수의 요소가있는 배열로 지정되기 때문에 스택에 할당됩니다. 값은 malloc, new 등의 힙에만 배치됩니다.
Seth Johnson

6
모든 자동 변수는 스택에 할당됩니다. 디스 어셈블을 보면 스택 포인터에서 뺀 로컬 변수의 크기를 볼 수 있습니다. malloc 또는 calloc 또는 메모리 기능 중 하나를 호출하면 기능이 이동하여 요구 사항을 충족 할 수있을만큼 큰 메모리 블록을 찾습니다.
다시 실행

@Charles 스택이 아닌 힙에서 더 많은 메모리를 할당 할 수있는 이유는 무엇입니까? 내 이해에서 스택과 힙은 메모리의 할당 된 주소 공간에서 반대 방향으로 이동합니다.
saurabh agarwal 2015

2
@saurabhagarwal 힙이 움직이지 않습니다. 연속적인 메모리 영역도 아닙니다. 할당자는 단순히 크기 요구 사항에 맞는 여유 메모리 블록을 반환합니다 . 스택과 힙은 무엇이며 어디에 있습니까?
phuclv

56

C 또는 C ++에서 로컬 개체는 일반적으로 스택에 할당됩니다. 스택에서 처리 할 수있는 것보다 더 많은 큰 배열을 스택에 할당하므로 스택 오버플로 가 발생합니다 .

스택에 로컬로 할당하지 말고 대신 다른 장소를 사용하십시오. 이는 객체를 전역으로 만들 거나 전역 에 할당 하여 수행 할 수 있습니다 . 다른 컴파일 단위에서를 사용하지 않으면 전역 변수가 괜찮습니다. 이것이 우연히 발생하지 않도록하려면 정적 저장소 지정자를 추가하고 그렇지 않으면 힙을 사용하십시오.

이것은 힙의 일부인 BSS 세그먼트에 할당됩니다.

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

이는 힙의 일부인 DATA 세그먼트에 할당됩니다.

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

이것은 힙의 지정되지 않은 위치에 할당됩니다.

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

힙에 할당하는 세 번째 패턴을 사용하는 경우 어떤 단계에서 포인터를 삭제 []하는 것을 잊지 마십시오. 그렇지 않으면 메모리가 누수됩니다. 또는 스마트 포인터를 살펴보십시오.
davidA 2012-09-05

8
@meowsqueak 물론 delete할당 하는 모든 곳에서 좋은 습관 입니다 new. 그러나 메모리를 한 번만 할당한다고 확신하는 경우 (메인에서와 같이) 엄격하게 필요하지 않습니다. 메모리는 명시 적 없이도 main 종료시 해제됩니다 delete.
Gunther Piez 2012 년

'at'drhirsch (어쨌든 at- 문자는 어떻게합니까?)-예, 공정한 의견입니다. OP가 언어에 새로운 것처럼 보이기 때문에 나는 그들과 당신의 좋은 대답을 보는 다른 사람들이 일반적으로 사용되는 경우 세 번째 옵션의 의미를 알고 있는지 확인하고 싶었습니다.
davidA 2012-09-05

15

또한 대부분의 UNIX 및 Linux 시스템에서 실행중인 경우 다음 명령을 사용하여 일시적으로 스택 크기를 늘릴 수 있습니다.

ulimit -s unlimited

그러나 조심하십시오. 기억은 제한된 자원이며 큰 힘으로 큰 책임이 따릅니다. :)


1
이것이 해결책이지만 프로그램의 스택 크기에 대한이 기본 제한을 제거 할 때 모든 사람이 극도로주의 할 것을 권고합니다. 심각한 성능 저하를 경험할뿐만 아니라 시스템이 충돌 할 수 있습니다. 예를 들어, 4GB RAM이있는 시스템에서 퀵 정렬을 사용하여 16,000,000 정수 요소로 배열을 정렬하려고했는데 시스템이 거의 종료되었습니다. LOL
rbaleksandar

@rbaleksandar 배열의 여러 복사본으로 작업하고 있었기 때문에 ~ 16MB 프로그램이 거의 기계를 죽일 것이라고 생각합니다 (함수 호출 당 하나 일 수 있습니까?) 더 많은 메모리 인식 구현을 시도하십시오;)
RSFalcon7

나는 값이 아닌 참조로 전달하기 때문에 배열 처리가 괜찮다고 확신합니다. bubblesort에서도 똑같은 일이 발생합니다. 지옥, 퀵 정렬의 구현이 거품 정렬을 짜증나게하더라도 잘못 구현할 수는 없습니다. LOL
rbaleksandar

LOL 기수 정렬을 시도하거나 단순히 std :: sort를 사용할 수 있습니다. :)
RSFalcon7

1
기회 없음. 실험실 과제입니다. : D
rbaleksandar 2014 년

3

이 경우 배열이 스택에 할당되고 있으며이 경우 alloc을 사용하여 동일한 크기의 배열을 할당하려고합니다.


3

스택에 배열을 저장하기 때문입니다. 힙에 저장해야합니다. 힙 및 스택의 개념을 이해하려면 이 링크 를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.