2013-05-10 5 views
2

왜이 코드를 ppp없이 실행하면 트리플 포인터가 정상적으로 실행되고 42 번 세 번 인쇄됩니까? 그러나 트리플 포인터를 포함하면 SetupAll 함수에서 seg 오류가 발생합니다. 내 생각에 ppp는 다른 두 포인터와 동일한 형식을 사용하여 i를 얻습니다. 도움?포인터에 대한 포인터

+0

디버그 할 때'SetupAll'을 입력 할 때'p','pp','ppp'의 원시 포인터 값은 무엇입니까? – Dai

답변

4

초기화하기 전에 포인터를 역 참조하기 때문에 충돌이 발생합니다. ppp을 가지고 있지 않더라도 동일한 문제가 발생합니다. 운이 좋았고 어떻게 든 충돌하지 않았습니다. SetupAll에서

#include <stdio.h> 
void SetupAll(int *iPtr, int **p, int ***pp, int ****ppp){ 
    *p = iPtr; 
    *pp = p; 
    *ppp = pp; 
    printf("hi\n"); 
} 

int main() { 
    int i = 42, *p, **pp, ***ppp; 
    SetupAll(&i, &p, &pp, &ppp); 
    printf("%u %u %u %u\n", ***ppp, **pp, *p, i); 
} 

공지 사항의 차이 - 당신이 그 값을 설정할 수 있도록 한 번만 각 포인터를 역 참조있다 : 당신이해야 할 의도가 무엇

는 다음과 같습니다. 선언의 나머지 "별"은 포인터가 가리키는 유형을 알려줍니다.

편집 : 당신이 **pp을 수행 할 때, 당신은 실제로 *(*pp)을하고, 정교합니다 - 즉 (a)는 첫 번째 자체가 (나)를 찾아보십시오 다음의 int에 대한 포인터입니다 *pp의 가치를 찾을 수 그 값이 *pp 인 int의 값. 하지만 원래 코드에서 아직 *pp을 초기화하지 않았으므로 임의의 위치를 ​​가리 킵니다. 따라서 (b)에서 int의 값을 찾으려고 할 때 *pp에 의해 반환 된 임의의 값이 유효한 메모리 주소가 아닌 경우 쉽게 충돌 할 수 있습니다.

+2

좋은 답변입니다. 보충 적으로 선언 할 때 null을 가리키는 포인터를 초기화하는 것이 좋습니다. 이렇게하면 "운이 좋은"상황을 피할 수 있지만 실제로는 "운이 좋지 않은"상황을 피할 수 있습니다. 항상 충돌이 발생할 때를 알 수없는 것보다 항상 좋을 수 있습니다. –

+0

아, 탁월한 점, @duskast. 언제나 충돌은 무작위 충돌보다 확실히 좋습니다! 나는 그것을 답에 추가 할 수 있지만 원래 코드와 유일한 차이점은 참조 해제에있는 것이 분명합니다. – Corey

0

메모리 오류를 언 마스킹하는 도구 인 valgrind를 사용하여이 문제를 디버깅하는 것이 도움이됩니다.

디버그 기호를 컴파일하고 Valgrind의 아래를 실행

$ cc test.c -o test -g 
$ valgrind ./test 
[...] 
Use of uninitialised value of size 8 
    at 0x100000E85: SetupAll (test.c:4) 
    by 0x100000ED3: main (test.c:11) 
Invalid write of size 8 
    at 0x100000E85: SetupAll (test.c:4) 
    by 0x100000ED3: main (test.c:11) 
Address 0x0 is not stack'd, malloc'd or (recently) free'd 

4 호선 것은 이것이다 :

**pp =iPtr; 

그래서 당신은 당신이 역 참조 *p을 시도 할 때 그 Valgrind의 프로그램을 종료 볼 수 있습니다, 초기화되지 않은 값.

관련 문제