2010-07-22 7 views
1

여기서 len은 A [10]이고 i은 A [11]에있다. 이러한 오류를 잡을 수있는 방법이 있습니까 ?? gcc -Wall -W를 사용하여 컴파일을 시도했지만 경고가 표시되지 않았습니다.배열 색인을 사용하여 다른 변수에 액세스 할 수있는 이유는 무엇입니까?

int main() 
{ 
    int A[10]; 
    int i, len; 
    len = sizeof(A)/sizeof(0[A]); 
    printf("Len = %d\n",len); 
    for(i = 0; i < len; ++i){ 
    A[i] = i*19%7; 
    } 
    A[i] = 5; 
    A[i + 1] = 6; 
    printf("Len = %d i = %d\n",len,i); 
    return 0; 
} 

출력 : 렌 = 10 렌 I = 5 = 6

+3

정의되지 않은 동작이라고하며 배열의 경계를 벗어날 때 얻을 수 있습니다. 이것은 어떤 일이 발생할 수 있으며 귀하의 프로그램이 더 이상 보증되지 않음을 의미합니다. – GManNickG

+1

우와, 왜 sizeof (0 [A])를 사용하고 있습니까? 다른 사람들이 귀하의 코드를 이해할 때 정말로 좋아하지 않는 한 sizeof (A [0]) 여야합니다. – nmichaels

+1

여기서 모든 대답은'sizeof (0 [A])'를 설명하는 방법을 알아야한다는 조건이 있어야합니다. 야생 추측 :이 숙제입니까? –

답변

7

어레이의 경계 외부 메모리에 액세스하고; C에서는 배열 인덱스에 대한 경계 검사가 없습니다.

기술적으로 배열 끝을 넘어 메모리에 액세스하면 이 정의되지 않은 동작이됩니다. 이것은 당신이 그것을 할 때 일어나는 일에 대한 보장이 없다는 것을 의미합니다. 귀하의 예제에서는 다른 변수가 차지하는 메모리를 덮어 씁니다. 그러나 정의되지 않은 동작으로 인해 응용 프로그램이 중단되거나 악화 될 수도 있습니다.

이러한 오류를 포착 할 수있는 방법이 있습니까?

컴파일러는 이와 같은 오류를 catch 할 수 있지만 많지는 않습니다. 컴파일 타임에 이런 종류의 오류를 잡아 경고를내는 것은 종종 불가능합니다.

정적 분석 도구는 이러한 종류의 오류의 다른 인스턴스를 포착 할 수 있으며 일반적으로 이런 종류의 오류를 일으킬 수있는 코드에 대한 경고를보고하기 위해 작성됩니다.

+0

코드를 정적으로 분석하기 위해 부목을 사용했지만이 오류를 포착하지 못했습니다. – Inception

+0

@Inception : 컴파일 타임에 이런 종류의 오류를 감지하는 것이 종종 불가능합니다. –

0

나는 메모리의 위치가 A의 끝 부분을 지나치고있다. 모든 컴파일러와 모든 아키텍처에서 보장 할 수는 없지만, 다른 방법으로는 할 수없는 이유가 거의 없을 것이다.

0에서 9까지 세는 것은 10 가지 요소입니다.

2

C는 일반적으로 경계 검사를 수행하지 않지만 많은 사람들이 C에 대한 경계 검사를 구현했습니다. 예를 들어 http://sourceforge.net/projects/boundschecking/에 GCC 용 패치가 있습니다. 물론 경계 검사에는 약간의 오버 헤드가 있지만 파일별로 활성화되거나 비활성화 될 수 있습니다.

1

A의 배열 할당은 메모리에서 i와 len에 인접합니다. 배열을 통해 주소를 지정할 때 포인터를 사용하는 것과 똑같은 점을 기억하십시오. 배열의 마지막 부분을 벗어나 다른 위치에 배치해야합니다.

C는 기본적으로 경계 검사를 수행하지 않습니다. 당신은 프로그래머로서 조심해야합니다. 교환에서 당신은 속도와 크기 이점을 얻습니다.

일반적으로 lint와 같은 외부 도구는 정적 코드 분석을 통해 문제를 포착합니다. 컴파일러 공급 업체에 따라 일부 라이브러리는 패딩이나 메모리 보호 기능을 추가하여 끝까지 걸어 나갔을 때를 감지합니다.

"위험한 점"의 메모리에는 흥미롭고 위험하며 휴대하기 어려운 것들이 많이 있습니다. 힙 메모리 할당을 유지하는 대부분의 집은 컴파일러가 제공하기 전에 메모리 위치에서 발생합니다.

할당하지 않았거나 요청하지 않은 경우 일반적으로 규칙이 적용됩니다.

+0

다음을 확인하십시오. http://williambader.com/bounds/example.html 힙 관리 메모리 용입니다. 정적 코드 분석을 위해 http://www.gimpel.com/을 살펴보십시오. –

0

배열 인덱싱은 0부터 시작합니다. 따라서 배열 크기는 선언 된 값보다 작은 값과 같습니다.당신은 허용 된 것 이상으로 메모리를 덮어 씁니다.

이러한 오류는 경고로보고되지 않을 수 있지만 prevent, sparrow, Klockworks 또는 purify와 같은 도구를 사용하여 이러한 "부적절한 행위"를 찾을 수 있습니다.

0

간단히 대답하면 지역 변수는 스택에 있고, 인덱싱은 * (ptr + index)와 같습니다. 그래서 int y [N]의 공간이 다른 int x의 공간에 인접 해있을 수 있습니다. 예 : x는 마지막 y 다음에 위치합니다. 그래서 y [N-1]은 마지막 y이고, y [N]은 마지막 y를 지나간 int입니다.이 경우 실수로 x가 생깁니다. 그러나 배열의 범위를 넘어서서 그 것에 의존 할 수없는 것은 확실한 사실이 아닙니다. 감지되지는 않지만 "인덱스 밖의 오류"이며 버그의 원인입니다.

관련 문제