2011-11-11 4 views
2

포트란에서 C++로 프로그램을 변환하고 있습니다.3 차원 배열 선언으로 인해 세그먼트 화 오류가 발생합니다.

float TC[100][100][100]; 

그리고 내가 그것을 실행하면 그때는 분할 오류 오류 :이 배열 선언을 추가 할 때까지

내 코드는 잘 실행 것으로 보인다. 이 배열은 8MB의 메모리를 차지하며 내 컴퓨터는 3GB를 차지합니다. 이 선언에 문제가 있습니까? 내 C++은 꽤 녹슬다.

+1

분할 오류가 일반적으로 발생 당신이 허용되지 않는 메모리에 액세스하려고 할 때. 배열의 한계를 넘어선 적이 있습니까? – lvella

+0

그 배열은 실제로 4MB보다 작은 공간을 필요로합니다. –

답변

3

TC이 자동 로컬 변수로 할당되고 있다고 생각합니다. 이것은 그것이 스택에 저장되고 있음을 의미합니다. 스택 메모리가 4MB가되지 않으므로 스택 오버플로가 발생합니다.

해결하려면 구조화 된 컨테이너 또는 new과 함께 동적 할당을 사용하십시오.

+0

도움 주셔서 감사합니다! 나는 Fortran에서 그런 것들을 다룰 필요가 없었기 때문에 그것에 대해 조금은 모릅니다. – user1042343

0

이것은 스택 기반 선언처럼 보입니다. 힙에서 할당 해 봅니다 (예 : new 연산자 사용).

0

함수 내부에서 로컬 변수로 선언하는 경우 스택에 크기가 커서 배열에 맞지 않을 수 있습니다. new 또는 malloc()으로 힙에 할당하거나 디자인에서 허용하는 경우 전역 변수로 지정할 수 있습니다.

0

C++에서 스택에는 제한된 공간이 있습니다. MSVC는이 크기를 1MB로 기본 설정합니다. 스택이 1MB 이상을 사용하면 segfault 또는 stackoverflow 또는 무언가가 발생합니다. 이 구조체를 동적 메모리로 이동해야합니다. 동적 메모리로 이동하려면 이런 식으로 뭔가를 원하는 : 가변 배열, 그것은 액세스 할 때 처음으로 동적 메모리 구조를 할당합니다

typedef float (bigarray)[100][100][100]; 
bigarray& TC() { 
    static bigarray* ptr = NULL; 
    if (ptr == NULL) { 
     ptr = new float[100][100][100]; 
     for(int j=0; j<100; j++) { 
      ptr[j] = new float[100][100]; 
      for(int i=0; i<100; i++) 
       ptr[j][i] = new float[100]; 
     } 
    } 
    return *ptr; 
} 

. 당신은 사각형 배열에서 더 많은 성능을 얻을 수 있지만, 당신은 유형을 변경해야합니다 :

typedef std::vector<std::array<std::array<float, 100>, 100> bigarray; 
bigarray TC(100); 

http://cs.nyu.edu/exact/core/doc/stackOverflow.txt에 따르면, GCC/리눅스 기본적으로 당신의 구조 충분히 크지 않다 8메가바이트에 스택의 크기,int main() 정말로 원한다면 MSVC에는 스택 크기를 32MB까지 늘릴 수있는 플래그가 있습니다. Linux에는 ulimit 명령이있어 최대 32MB의 스택 크기를 늘릴 수 있습니다.

+0

고마워요! 이것은 꽤 도움이됩니다. – user1042343

3

그 배열은 약 4 메가 ​​바이트입니다. 이 정의가 함수 내부에있는 경우 (로컬 변수로) 컴파일러는 스택에 저장하려고 시도합니다. 스택에서는 대부분의 시스템에서 그 정의를 커질 수 없습니다.

아마도 Fortran 컴파일러는 정적으로 할당했습니다 (포트란 루틴은 재귀 적으로 명시 적으로 표시되지 않으면 Fortran 루틴을 재귀 적으로 호출 할 수 없으므로 비 재귀 함수에 대해 정적 변수 할당이 작동하므로 오류가 발생하지 않습니다). 그곳에.

Fortran 함수가 재귀 적으로 선언되지 않았다고 가정하면 변수 static을 명시 적으로 선언하는 것이 좋습니다. 그러나 수정 된 버전에서 해당 함수를 재귀 적으로 호출하려고 시도하면 나중에이 문제가 발생할 수 있습니다. 그래서 더 나은 해결책은 아마 그것을 동적으로 할당하는 것입니다. 그러나 코드 시간이 길어 코드의 특성에 따라 성능이 너무 많이 손상 될 수 있습니다 (Fortran 코드는 성능 문제가있는 숫자 코드입니다).당신이 배열이 정적하도록 선택할 경우

, 당신은 실수로 재귀 호출에 대한 보호에 구축 할 수 있습니다 :

void yourfunction() 
{ 
    static bool active; 
    static float TC[100][100][100]; 

    assert(!active); 
    active = true; 

    // your code 

    active = false; 
} 
관련 문제