2014-05-14 9 views
1

동적으로 생성 된 배열의 크기를 줄이는 데 어려움이 있습니다. 이 64를 인쇄,하지만 난 그게에 예상대로 세그먼트 폴트 오류가 발생하지realloc이 배열을 축소하지 않는 이유는 무엇입니까?

int main(void) { 
    // Intialize big array 
    int * a = (int *)malloc(10*sizeof(int)); 
    assert(a); 
    // Fill it with squares 
    for (int i = 0; i < 10; ++i) 
     a[i] = i*i; 
    // Expected to print 64 
    printf("%d\n", a[8]); 
    // Shrink the big array 
    int * b = (int *)realloc(a, 5*sizeof(int)); 
    assert(b); 
    // Expected to cause SEGFAULT 
    printf("%d\n", b[8]); 
    return 0; 
} 

모든 것이, printf("%d\n", b[8]); 라인을 제외하고 잘 작동 : 여기처럼 내 main 기능이 어떻게 표시되는지를 보여줍니다. 왜?

내가 간단한 것을 놓친 것 같아. 왜냐하면 나는 realloc으로 메모리를 축소하는 것과 관련된 많은 의문점을 봤지만, 모두 가능하다고 말하기 때문이다.

저는 GCC 4.8.2에서 우분투 14.04를 사용하고 있습니다. -std=c99 옵션으로 컴파일하고 있습니다.

+1

지난 몇 일간이 질문 또는 거의 동일한 질문을 받았지만 바로 찾을 수 없습니다. 'realloc()'은 사용 가능한 메모리의 내부 풀에 메모리를 반환하지만 그것으로부터 읽거나 쓰려고하면 정의되지 않은 행동이 발생하지만 일반적으로 메모리를 매핑 해제하지 않으므로 일반적으로 액세스하면 충돌이 직접 발생하지 않습니다 -하지만 해제 된 메모리에서 읽는 것은 매우 나쁜 습관이며, 해제 된 메모리에 쓰는 것은 훨씬 나빠집니다. –

+0

_ {Rewrite} _ 제안 된 복제본에 대해 확실하지 않습니다. 제안 된 복사본은'realloc()'또는'malloc()'과 아무런 관련이 없습니다. 현재로서는 필자가 지적하기에 좋은 복제본이 없지만 철저한 검색을 수행하지는 않았습니다.나는 내가 기억하고 있다고 생각했던 '가까운 곳으로 가깝다'는 것이 OP에 의해 삭제 된 것으로 의심된다. 전체적으로이 것을 열어 두십시오. –

+1

예,이 질문과 제안 된 복제본 모두는 배열의 경계 밖에서 데이터를 읽고 쓰는 것에 관한 것입니다.이 경우에는 동적으로 할당되고 다른 하나는 일반 (전역 변수)으로 할당됩니다. 그 정도까지, 그들은 중복됩니다. 그러나 할당 된 공간이 줄어들 때까지 합법적이었던 것을 액세스하는 것에 비해 부정적인 인덱스에 중점을 두는 것이 차이가 있다고 생각합니다. 중복 클로저에 대해서는 논쟁을하지 않겠지 만, 동적으로 할당 된 메모리와 축소를보다 명확하게 처리하는 중복 된 복사본을 찾는 것을 선호합니다. –

답변

8

b[8] 두 번째 printf의 호출은 할당되지 않은 메모리에 액세스하고 정의되지 않은 동작을 호출합니다. 그것이 기본적으로 정의되지 않은 행동의 의미입니다. 결과는 예측할 수 없습니다. 그것은 잘 작동하고있는 것처럼 보일지도 모르지만 다음 번에 아주 잘 충돌 할 수 있습니다. 여기에서 고려해야 할 몇 가지 다른 일이 있습니다 -

  • malloc이 때문에 assert 매크로 반환 값을 확인 메모리를 할당하는 데 실패 할 수는 잘못된 것입니다. assert은 바인딩 범위 밖의 배열에 액세스하는 것과 같이 불가능하거나 잘못된 코드를 디버그하는 데 사용해야합니다.

  • 결과는 malloc이 아닙니다. Do I cast the result of malloc?

  • reallocmalloc과 같은 메모리 블록을 재 할당하지 못할 수 있습니다. 실패하면 NULL을 반환하고 이전 블록을 변경하지 않습니다. 즉, 이전 메모리 블록에서 핸들을 잃어서 누출 될 수 있습니다. realloc을 호출하기 전에 변수에 이전 블록에 대한 포인터를 저장해야합니다.

5

할당되지 않은 공간에 액세스하고 있습니다. 그것은 정의되지 않은 동작입니다. 최악의 경우, 지금도 마찬가지입니다. Segfault는 보장 될 수 없습니다.

+1

@frostnational은 동일한 주소에 메모리를 유지하는 realloc에 ​​의존하지 않습니다. – Balu

1

Realloc은 향후 malloc 작업에 사용할 수있는 나머지 버퍼를 표시합니다. UB입니다. 버퍼에 malloc이없는 경우 버퍼에 계속 액세스 할 수 있습니다. 이는 사용자의 경우에 발생합니다. 할당되지 않은 메모리에 액세스 할 때 segfault가 발생하지 않는 것이 좋습니다.

액세스하는 메모리가 처리 여부에 속하는 경우 따라서는 충돌하거나 수없는 다음 작업을 수행 할 때이, 정의되어 있지
1

:

당신이 그것을 직접 확인해야
int i; 
int a[5]; 
for(i=0;i<10;i++) 
    printf("%d\n", a[i]); 

.