C++

C++ 댕글링, 보이드, 널, 와이드 포인터

김구티2 2024. 5. 16. 19:36

C에서 프로그래밍 포인터는 메모리 주소를 조작하거나 일부 변수 또는 메모리 위치의 주소를 저장하는 데 사용된다. 그러나 포인터와 관련된 특정 상황과 특성은 메모리 안전 및 프로그램 동작 측면에서 어려워진다. 여기에는 Dangling(할당 해제된 메모리를 가리킬 때), Void(특정 유형이 없는 일부 데이터 위치를 가리킬 때), Null(유효한 주소의 부재) 및 Wild(초기화되지 않은) 포인터가 포함된다.

1. 댕글링 포인터

삭제(또는 해제)된 메모리 위치를 가리키는 포인터를 댕글링 포인터(dangling pointer)라고 한다. 이러한 상황은 프로그램에서 예기치 않은 행동을 초래할 수 있으며, C 프로그램에서도 버그의 원인이 될 수 있다.

포인터가 댕글링 포인터 역할을 하는 것에는 세 가지 방법이 존재한다.

 

① 메모리 할당 해제
포인터가 가리키는 메모리가 할당 해제되면, 포인터는 댕글링 포인터가 된다.

 

메모리 할당 해제 예시:

// C program to demonstrate Deallocating a memory pointed by
// ptr causes dangling pointer
#include <stdio.h>
#include <stdlib.h>

int main()
{
     int* ptr = (int*)malloc(sizeof(int));

     // After below free call, ptr becomes a dangling pointer
     free(ptr);
     printf("Memory freed\n");

     // removing Dangling Pointer
     ptr = NULL;

     return 0;
}

 

출력:

Memory freed

 

② 함수 호출
로컬 변수가 정적이지 않고 함수가 해당 로컬 변수에 대한 포인터를 반환할 때. 로컬 변수를 가리키는 포인터가 댕글링 포인터가 된다.

 

로컬 변수가 정적이 아닐 때 댕글링 포인터 예시:

// C program to demonstrate the pointer pointing to local
// variable becomes dangling when local variable is not
// static.
#include <stdio.h>

int* fun()
{
     // x is local variable and goes out of
     // scope after an execution of fun() is
     // over.
     int x = 5;

     return &x;
}

// Driver Code
int main()
{
     int* p = fun();
     fflush(stdin);

     // p points to something which is not
     // valid anymore
     printf("%d", *p);
     return 0;
}

 

출력:

0

 

위의 예시에서 p는 포인터에 의해 값이 반환되는 즉시 로컬 변수(x)가 파괴됨에 따라 댕글링이 된다. 이는 아래 예시와 같이 변수 x를 정적 변수로 선언함으로써 해결할 수 있다:

// The pointer pointing to local variable doesn't
// become dangling when local variable is static.
#include <stdio.h>

int* fun()
{
     // x now has scope throughout the program
     static int x = 5;

     return &x;
}

int main()
{
     int* p = fun();
     fflush(stdin);

     // Not a dangling pointer as it points
     // to static variable.
     printf("%d", *p);
}

 

출력:

5

 

③ 변수가 범위를 벗어남
변수가 범위를 벗어날 경우, 해당 변수를 가리키는 포인터는 댕글링 포인터가 된다.

 

예시:

// C program to demonstrate dangling pointer when variable
// goes put of scope
#include <stdio.h>
#include <stdlib.h>

// driver code
int main()
{
     int* ptr;
     // creating a block
     {
          int a = 10;
          ptr = &a;
     }

     // ptr here becomes dangling pointer
     printf("%d", *ptr);

     return 0;
}

 

출력:

2355224

2. 보이드 포인터

보이드 포인터는 특정 유형이 없는 저장소의 일부 데이터 위치를 가리키는 포인터다. 그러니까 보이드 포인터는 유형을 나타내는 것으로 이해하면 된다. 기본적으로 해당 포인터가 가리키는 데이터 유형은 임의의 것이 될 수 있다. 모든 포인터 유형은 보이드 포인터로 변환 가능하므로, 모든 값을 가리킬 수 있다.

보이드 포인터는 재참조할 수 없다. 그러나 보이드 포인터를 유형 캐스팅하여 수행할 수 있다. 보이드 포인터의 구체적인 값과 크기가 부족하기 때문에 포인터 산술을 사용할 수는 없다.

 

구문:

void *ptrName;

 

 임의의 포인터 유형으로 변환 가능한 void 포인터 예시:

// C program to demonstrate the void pointer working
#include <stdlib.h>

int main()
{
     int x = 4;
     float y = 5.5;

     // A void pointer
     void* ptr;
     ptr = &x;

     // (int*)ptr - does type casting of void
     // *((int*)ptr) dereferences the typecasted
     // void pointer variable.
     printf("Integer variable is = %d", *((int*)ptr));

     // void pointer is now float
     ptr = &y;
     printf("\nFloat variable is = %f", *((float*)ptr));

     return 0;
}

 

출력:

Integer variable is = 4
Float variable is = 5.500000

3. 널 포인터

NULL 포인터는 아무것도 가리키지 않는 포인터다. 즉, 유효한 개체나 메모리 위치를 가리키는 것이 아니다. 포인터에 할당할 주소가 없는 경우 NULL을 사용하면 된다. NULL은 유효한 메모리 주소가 없음을 나타내는 데 사용된다.

 

구문:

datatype *ptrName = NULL;

 

예시:

// C program to show the value of NULL pointer on printing
#include <stdio.h>
int main()
{
     // Null Pointer
     int* ptr = NULL;

     printf("The value of ptr is %p", ptr);
     return 0;
}

 

출력:

The value of ptr is (null)

 

* NULL vs Void Pointer: 널 포인터는 값이고 보이드 포인터는 유형이다.

4. 와일드 포인터

임의의 것(NULL도 아님)으로 초기화되지 않은 포인터를 와일드 포인터(Wild Pointer)라고 한다. 포인터는 유효한 주소가 아닐 수 있는 NULL이 아닌 가비지 값으로 초기화될 수 있다.

 

구문:

dataType *pointerName;

 

예시:

#include <stdio.h>

int main()
{
     int* p; /* wild pointer */

     // trying to access the value pointed by a wild pointer
     // is undefined behavior
     // printf("Value pointed by wild pointer: %d\n", *p);
     // //give error
    
     int x = 10;

     // Accessing the value pointed by 'p'
     printf("Value pointed by 'p' is: %d\n", *p);

     return 0;
}

 

출력:

Segmentation Fault (SIGSEGV)
timeout: the monitored command dumped core
/bin/bash: line 1:    32 Segmentation fault

728x90

'C++' 카테고리의 다른 글

C++ 레퍼런스(참조, Reference) 총정리  (0) 2024.05.18
C++ 포인터 응용  (0) 2024.05.17
C++ 포인터 산술(Pointer Arithmetic)  (1) 2024.05.01
C++ 포인터(Pointers) 총정리  (0) 2024.04.29
C++ 포인터와 레퍼런스 정리  (0) 2024.04.29