[C++ 기초] 동적 할당(2), 댕글링 포인터, 라이브러리 만드는 방법

라멘커비·2024년 1월 4일
0

CPP 입문

목록 보기
16/25
post-thumbnail

동적 할당(2)

new 연산자로 동적 할당을 하면 리턴 값을 포인터로 받아서 사용해야 한다.
아래 두 영역의 코드는 할당 방식이 다르지만 매우 흡사한 코드이다.

{
	// 정적 할당
    int Value = 0;
    int* Ptr = &Value;
}
{	
	// 동적 할당
    int* Ptr = new int(0);
}

🌳동적 할당 필요성

어떤 메모리를 원할 때 원하는 만큼 생성할 수 있다. C스타일 동적할당(malloc, remalloc, free)은 추후에 번외(?)로 배울 예정이다.
배열을 동적으로 할당할 수 있다는 것의 의미가 크다. If문 등과 연계하면 많은 것이 가능해진다.

  • 소유의 개념을 표현할 수 있게 된다.
    Has-A 관계는 가지고 있다는 의미인데, 현실에서는 가지고 있을 수도 있고 없을 수도 있다. 그런 개념 및 관계를 표현할 수 있게 된다.

🌳동적 할당 주의점

  • new 연산을 하고 리턴값을 포인터로 받지 않으면 100% 확률로 leak이 된다.
    힙 영역에 메모리가 생성되지만 메모리를 명시해서 접근하거나 사용할 수 없다. 그 메모리를 delete할 수도 없기 때문에 무조건 leak이 되는 것이다.
	new int(10); // X, 리턴 값을 받지 않음
	reinterpret_cast<int*>(operator new(sizeof(int))); // new int()의 본모습
  • new 연산을 하면 delete를 최우선으로 작성해야 한다.

🌳포인터 관련 주의점

동적 할당한 곳에 또 할당하지 말기

아래 예시에서 먼저 할당됐던 500번지(예시)의 int 메모리는 leak이 되어버렸다.

	int* Ptr = new int();	// 500번지에 메모리 생김, Ptr은 500번지 가리킴
	Ptr = new int();		// 600번지에 메모리 생김, Ptr은 600번지 가리킴
    
    delete Ptr;				// 600번지만 delete됨

방어코드를 치기

nullptr은 사용할 수 없다.
nullptr 체크는 무조건 해야 한다.

	int* Ptr = nullptr;
	//*Ptr = 200;		<- null 레퍼런스 익셉션 발생함
	if (nullptr != Ptr) {
		*Ptr = 200;
	}
  • 방어코드를 치지 않아 nullptr에 접근할 경우 null reference exception 발생한다.

댕글링 포인터 Dangling Pointer(허상 포인터)

동적 할당을 하면 힙영역의 주소가 나온다.

delete를 하고 나서 포인터가 nullptr이 되는 것이 아니다. (delete 후 어디를 가리키게 되는지는 컴파일러에 따라 다를 수도 있고 어찌되는지 모르는 일이다.)

그래서 이런 코드가 안 먹힘.
아래 코드에서 *Ptr = 20; ← 이걸 댕글링포인터라고 한다. 쓰기 엑세스 위반 예외가 발생한다.

  • delete 하고 nullptr을 넣어주고 방어코드까지 사용하는 것이 안전하다.

safe delete 형식

nullptr을 delete하는 것은 좋은 코드가 아니다. (delete 내부에서 방어해주긴 함)
0번지를 해제하는 것은 말이 안 됨.

int* Ptr = nullptr;

if (nullptr != Ptr) {
	delete Ptr;
	Ptr = nullptr;
}

라이브러리 만드는 방법

🌳비주얼 스튜디오에서 라이브러리 프로젝트 만드는 방법

1. 새 프로젝트를 만든다. (정적 라이브러리 옵션으로 만들어도 되지만 빈 프로젝트로 하는 방법)

새 프로젝트 만든다.
ConsoleScreen을 만들어볼거다. 기본 필터는 전부 삭제함. (취향)

2. 콘텐츠 프로젝트 생성

만들고 싶은 게임 프로젝트 만든다.
ex) Galaga 갤러그 프로젝트

Galaga 프로젝트에서 ConsoleEngine의 클래스를 사용하고 싶다.( = ConsoleEngine 라이브러리를 사용하고 싶다.) → 다른 프로젝트니까 지금은 당연히 안 됨.

3. 헤더 사용 추가

  • Galaga 프로젝트의 속성 > 구성 > "모든 구성" 선택
  • Galaga 프로젝트의 속성 > 플랫폼 > "모든 플랫폼" 선택
  • 포함 디렉터리 > "..\;" 추가

4. 테스트용 함수 추가

라이브러리 프로젝트인 ConsoleEngine에 테스트용으로 함수를 만들고 그걸 컨텐츠 프로젝트인 Galaga에서 사용하는 것이 핵심.

  • ConsoleEngine 프로젝트의 ConsoleScreen 클래스의 Test 함수
  • Galaga 프로젝트의 main

5. 빌드해보면?

ConsoleScreen의 헤더만 사용이 가능해졌을뿐 cpp파일을 사용하는 설정은 하지 않았기 때문에 아직 구현된 내용은 사용하지 못하고 있다.

6. 컨텐츠 프로젝트에서 참조 설정

  • 컨텐츠 프로젝트인 Galaga에서 참조 추가 > ConsoleEngine 체크
    라이브러리로서 사용할 프로젝트를 참조 추가 해준다.

그래도 안 된다. 최초에 빈프로젝트로 만들었기 때문에 exe로 되어있는데 그 설정을 바꿔야 한다.

7. 라이브러리 프로젝트 설정

  • 라이브러리 프로젝트의 속성 > 구성 속성 > 일반 > 구성 형식 > "정적 라이브러리" 선택

  • 여기까지 하면 된다.

8. 프로젝트 종속성 확인

수동으로 프로젝트 종속성을 넣어줘야 할 수도 있다.

  • 솔루션 속성 > 프로젝트 종속성 > 컨텐츠 프로젝트 선택 > 라이브러리 프로젝트 체크
profile
일단 시작해보자

0개의 댓글

관련 채용 정보