2013-04-08 4 views
1
#include <iostream> 
using namespace std; 

int a[4]; 
int main(){ 
    int b=7; 
    cout<<a[b]<<endl; 
    return 0; 
} 

할당되지 않은 메모리에 액세스하려고했습니다. 그래서 출력이 세그멘테이션 오류가 될 것으로 예상합니다. 대신 출력이 일부 쓰레기 값입니다.다음 코드가 세그먼트 화 오류를 생성하지 않는 이유는 무엇입니까?

나중에 'b'를 1000으로 늘렸으므로 출력이 '분할 오류'입니다. 이런 종류의 행동에 대한 특별한 이유가 있습니까?

저는 gcc-4.3.2 컴파일러를 사용하고 있습니다.

+3

정의되지 않은 동작입니다. 그것은 당신이 알고있는 모든 것에 대해 "하나"를 부르는 뉴욕 하수구 쥐들의 코러스 라인을 만들 수 있습니다. 자세한 내용은 [이 답변] (http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior/4105123#4105123) 또는이 포럼의 다른 많은 사람들을 참조하십시오. – WhozCraig

+3

정의되지 않은 동작으로 인해 스피커에서 뜨거운 문제가 발생하면 창 밖으로 나갑니다. – chris

+1

실제로 무슨 일이 일어나는지 컴파일러가 정확히 무엇인지 알고 있지만 너무 많이 당신을 사랑하게하는 당신의 어머니에게 분할 결함을 메일로 보내는 것입니다. – jthill

답변

6

A segmentation fault은 존재하지 않는 메모리 주소 (외부의 프로세스의 주소 공간)에 액세스하려고 시도하면 throw 될 수 있습니다.

a[7]은이 경우 액세스 할 수있는 공간 외부에 있지 않을 수도 있지만 a[1000]이 가장 확실합니다. 하지만 당신이 가장 기대하지 않을 때 전자가 폭발 할 것입니다.)

+0

'a [1000]'은 반드시 프로세스의 가상 메모리 외부에있을 필요는 없습니다 (이 경우에도 마찬가지입니다). 그것은 당신의 OS에서 메모리 할당이 어떻게 구현되는지에 달려있다. – Anthony

0

범위를 벗어나는 액세스는 정의되지 않은 동작입니다. 프로세스 공간에서 임의의 메모리에 액세스 할 수 있습니다. 액세스 된 메모리가 프로세스 주소 공간 (커널에있을 수 있음)에 할당되지 않았 으면 세그먼트 화 오류로 인해 프로그램이 중단됩니다. 이 경우 오류는 문제를 식별하는 데 도움이되며 운이 좋으면 충돌이 발생하여주의를 끌지 못할 수 있으며 추후 추적하기 어려운 메모리를 손상시키는 프로그램의 버그가 발생할 것입니다. 할당되지 않은 [1000] 확률은 더 많고 따라서 충돌입니다. 메모리는 페이지 단위로 할당됩니다.

2

운영 체제에서 액세스를 허용하지 않은 메모리에 액세스하는 경우에만 세그먼트 오류가 발생합니다.

그러나 예기치 않은 메모리가 스택에 이전 또는 이후를 가리키는 메모리 주소와 같이 사용자에게 부여 된 메모리에 액세스 할 수 있습니다. 그러나 스택에 로컬로 저장된 변수가 스택에 배치되는 방식은 디버그에서 릴리스, 코드 변경 등에 따라 달라질 수있는 비전 최적화에 따라 컴파일러에서 결정됩니다.

하지만 뭔가 '왜이 변수에 액세스하면 쓰레기를 줄지 모르지만 항상 같은 쓰레기를 볼 수 있습니까?' 아마도 의도하지 않은 스택 부분을 엿볼 수 있습니다.

+0

'a'는 여기에 스택에 없습니다. –

1

아무 일도 일어나지 않도록 정의되지 않은 동작이므로, 그냥 알 수 없습니다. 정의되지 않은 동작, 지정되지 않은 동작 및 구현 정의 동작 간의 차이를 확인하려면 this out (C++의 경우)을 확인하십시오. 부속서 J의 명확한 설명은

C - **ISO C9899**입니다.

편집
C++ - 섹션 1.9.2, 1.9.3에서 N3485 ISO/IEC, 위의 행동에 대한 1.9.4 회담.

+0

대신 [C++ 표준] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)을 인용하면 안됩니까? –

+0

@AnishRam OP는이 태그에 ** C ** 및 ** C++ ** 태그를 붙였습니다. ** C++ **에 대한 링크에서 이미 표준에 대한 언급이 언급되어 있습니다. 그러나 ** C ** **에 대해서는 언급되지 않았으므로 명시 적으로 언급했습니다. –

+0

태그에 관계없이 코드는 C++입니다. –

0

segfaults를 발생 시키려면 정의되지 않은 동작이 필요하지 않습니다. 일반적으로 segfault를 발생시키지 않는 정의되지 않은 동작의 다른 예는 int i = INT_MAX + 1;을 고려하십시오.

관련 문제