2013-07-29 2 views
10

나는 87realloc 후 원래 포인터 사용 중?

if (++length > maximumLength) { 
    char *newBuffer = realloc (buffer, maximumLength += sizeIncrement); 

    if (newBuffer == NULL) { 
     free (buffer); 
     return NULL; 
    } 

    currentPosition = newBuffer + (currentPosition - buffer); 
    buffer = newBuffer; 
} 

나는 이름의 희망 페이지에서 리처드리스의 (2013 년 5 월) 새로운 오라일리 책 "이해 및 C 포인터 사용"을 읽고, 나는 거기에 몇 가지 코드에 대한 질문이 있었다 변수는 자명하다. 컨텍스트가 필요한 경우이 발췌가 아닌 전체 코드 묶음을 제공하도록 편집합니다.

제 질문은 라인 currentPosition = newBuffer + (currentPosition - buffer);입니다. realloc()에 대한 나의 이해는 새로운 할당이 성공하면 원래 할당 된 메모리가 해제된다는 것입니다. 그게 맞다면 문제의 라인은 매달려있는 포인터를 사용하고 있습니까? 해당 식의 RHS에있는 buffercurrentPosition은 모두 해제 된 메모리에 대한 포인터입니다.

어쨌든 length을 사용하여 매달려있는 포인터를 사용하지 않으려면이 내용을 다시 작성해야합니다. 나는 함께 그 마지막 두 줄을 교체하려면 : 두 개의 포인터는 여전히 (쓰레기이기는하지만) 주소를 유지하기 때문에 작성된 작품으로 아마도 그러나

buffer = newBuffer; 
currentPosition = buffer + length; 

, 코드, 그리고이 두 주소 사이의 오프셋은 여전히로 계산 될 수있다 재 할당 방법은 currentPosition입니다. 그래서 나는 이것에 대해 불안해하는 것에 지나치게 당황 스럽습니까?

질문을 일반화하려면 : 일단 포인터가 매달려 있으면 오프셋 계산과 같은 목적으로 포인터에 포함 된 주소를 사용하는 것이 안전합니까? 감사.

+0

재 할당시, 'length'는 버퍼 크기 (조정 전 최대 길이)보다 하나 큰 값입니다. 의미를 올바르게 해석하고 있다면'currentPosition = buffer + length - 1'을 사용해야합니다. – Casey

+0

실제로 질문을 게시하기 전에 확인했습니다. 이 책의 코드는'length'와'currentPosition'을 모두 0으로 초기화합니다. 'length'는 첫 번째 조건문에서 증가하기 때문에 항상 마지막에 추가 된 요소의 인덱스를 지난 것입니다. 'currentPosition'은 새로운 요소가 추가되는 곳이며, 추가 후에 증가합니다. 이 코드는 처음에는 코드를 작성하지 않았지만 주어진 코드를 사용하면'buffer + length'가 정확합니다. – verbose

+0

그래서'currentPosition'은 미리 구성된'buffer + length'입니까? 나는 정정 당했고 (이중화에 의해 다소 상상을 받았다). – Casey

답변

9

일단 포인터가 매달려 있으면 오프셋 계산과 같은 목적으로 포인터에 포함 된 주소를 사용하는 것이 안전합니까?

아니요, 안전하지 않습니다. free 다음에 포인터 값은 유효하지 않은 주소이고 유효하지 않은 주소는 정의되지 않은 동작을 호출하지 않고 포인터 연산에 사용할 수 없습니다.

+0

출처 나는 이것을 예상하지 못했습니다. –

+2

@CoryNelson C11, 6.5.6p8 포인터 연산. 결과가 배열 객체 또는 마지막 요소 => 정의되지 않은 동작 이후에없는 경우 – ouah

+1

@Ouah, 나는 이것이 결과를 역 참조하려고 할 때를 가리킨다 고 생각한다. – ROTOGG

0

포인터를 역 참조하지 않으려는 경우 (예 : 연산자 적용 *)에는 매달린 포인터 (예 : 포인터 연산)를 사용하는 것이 안전합니다.

+3

C 표준은 더 이상 존재하지 않는 객체에 대한 이전 포인터에 대한 산술 연산을 보장하지 않기 때문에 잘못되었습니다. 포인터가 메모리 주소로 구현되어 있고 주소에 대한 산술 연산이 가능하지만 포인터가 반드시 그런 식으로 구현되는 것은 아닙니다. 또한 옵티마이 저가 C의 규칙에 따라 공제 할 수 있으므로 놀라운 결과가 발생할 수 있습니다. –