정체불명의 모모
강의 내용 정리(Section5 / 버그 유형) 본문
강의 중 배운 내용과 추가적으로 배워야 할 부분들을 정리한 메모장 입니다.
강의 : (인프런) 게임 프로그래머 입문 올인원
버그 유형 / 메모리 릭 (memory leaks)
- 메모리 릭(memory leaks / 메모리 누수)
: 메모리 누수(memory leaks)는 C나 C++ 프로그래밍 과정에서 발견하거나 해결하기 가장 힘든 작업 중 하나 입니다.
시간이 지나 실행될 수록 메모리 공간을 잡아먹는다면 메모리 누수가 발생한 것 입니다.
메모리 누수는 할당했던 메모리를 제대로 해제 하지 않을 때 발생합니다.
▽ 간단한 예제 코드
#include <iostream>
#include <string>
using namespace std;
class Item
{
public:
Item() {}
~Item() {}
};
int main()
{
while (true)
{
Item* item = new Item(); // 할당
delete item; // 해제
}
return 0;
}
위 처럼 할당(new) 후 해제(delete)를 잘 하게 되면 아래의 스샷과 같이
메모리가 더 이상 상승하지 않는것을 확인 할 수 있습니다.
하지만 delete(해제) 하는 코드를 제거 하게 되면
미친듯이 프로세스 메모리를 잡아 먹는것을 확인 할 수 있습니다.
ㅁ 누수 체크 라이브러리 : <crtdbg.h> 라이브러리
#include <crtdbg.h>
_CrtDumpMemoryLeaks( );
위 라이브러리와 코드를 추가 시켜주면 아래와 같이 'Detected memory leaks!'란 말이 보입니다.
그리고 왜인지 프로세스 메모리도 이전과 다르게 급경사적으로 오르는것이 아닌 안정적으로 오르는걸 알 수 있습니다.
그리고 정확히 어떤 부분에서 문제가 발생 했는지 알고 싶으면 아래의 전처리 처리를 해주면 됩니다.
#if _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#define malloc(s) _malloc_dbg(s,_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
해당 코드를 넣어 주면 아래의 스샷과 같이 코드 어느 부분에 문제가 발생 했는지 친절히 알려줍니다.
ㅁ 그외에 누수 탐지 함수들
- CrtDumpMemoryLeaks();
- CrtSetDbgFlag( _CRTDGB_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
: 위 두 함수는 메모리 누수 결과를 디버그 결과 창에 표시해 준다.
- 첫 번째 함수는 메모리 문제로 인해 프로그램이 종료 되는 지점에 사용 하는데, 첫 누수 결과만 출력 한다.
여러 군데가 있다면 군데군데서 함수를 호출해야 하는 번거로움이 있다.
- 두 번째 함수는 프로그램의 시작 부분에 한 번 사용하면 탐지 가능한 모든 누수를 결과 창에 표시한다.
실시간으로 프로그램에 누수 결과를 알려주는 첫 번째 함수와는 달리 프로그램이 종료 되면 문제를 알려준다.
- CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG);
: 이 함수는 결과(보고서)의 출력 방식을 설정한다. 파일에도 설정할 수 있으며 assert 처럼 경고 창으로 띄울 수도 있다.
이 함수는 따로 사용하지 않아도 기본으로 결과 창엔 출력되기 때문에 추가로 설정 하고 싶다면 다음 링크를 참고 하자.
https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/crtsetreportmode?view=vs-2019 - CRTSetBreakAlloc( )
- crtBreakAlloc
: 네 번째 함수이고 다섯 번째는 매크로 인데, 둘 다 동일한 기능을 한다.
누수 발생 시 보고서에 누수 지점의 번호가 출력 되는데, 그 번호를 해당 함수의 인자로 전달하면 그 지점에서 멈춘다.
버그 유형 / 메모리 오염
: 메모리 오염은 사용자가 부주의하여 명확한 할당 없이 주소에 접근하여 데이터를 변경하려 하거나 잘못된 주소 위치로 접근
하려 하는 경우를 말한다.
ㅁ 메모리 오염이 발생 하는 상황
- Buffer Overflow 의 경우 할당된 메모리 양 보다 더 많은 데이터를 집어 넣을때 발생 한다.
- 할당한 배열을 초과하는 위치에 접근 하는 경우(인덱스 초과)
- 포인터 변수로 선언한 변수에 new로 메모리를 할당하지도 않았는데 포인터 주소를 가지는 멤버 변수나 함수로
접근 하는 경우 - free( ) or delete 로 날려버린 변수에 접근하는 경우 ---> User-After-Free
버그 유형 / Use-After-Free
: 반납을 완료한 동적 할당 메모리를 참조하여 사용할 경우 발생 합니다.
이미 반납된 메모리이므로, 다른 곳에서 할당 받아 사용할 가능성도 있으며, 이때 해당 메모리를 참조하여 값을 변경 할 경우
메모리 오염(Memory corruption) 발생 합니다.
동적할당(Dynamic memory allocated)된 heap을 free 하고
다시 재사용(Dynamic memory reuse) 할때 문제가 발생할 수 있다.
#include <iostream>
using namespace std;
class Monster
{
public:
Monster() { cout << "Monster()" << endl; }
~Monster() { cout << "~Monster()" << endl; }
public:
int _hp = 100;
};
int main()
{
Monster* m1 = new Monster;
delete m1;
cout << "메모리 오염 전 hp : " << m1->_hp << endl;
m1->_hp = 200;
cout << "메모리 오염 후 hp : " << m1->_hp << endl;
return 0;
}
ㅁ Use-After-Free 방지 하는 방법
: UAF 취약점을 방지하기 위해서는 메모리 해제 이후에는 해당 메모리를 참조하지 않도록 주의해야 한다.
- 포인터를 null로 초기화 하여 해당 메모리를 참조 하지 않도록 하는 방법
- 동적 메모리 할당 시에는 RALL(Resource Acquisition Is Initialization)등의 메모리 관리 기법을 이용하여 메모리를
자동으로 해제 할 수 있도록 하는 것이 좋다.
◆ RALL(Resource Acquisition Is Initialization)
: RALL는 C++에서 스마트 포인터, 파일 핸들러, 뮤텍스 등과 같이 자원 할당 코드와 자원 해제코드를 객체의
생성자와 소멸자에 각각 구현함으로써 메모리 누수를 방지하는 메모리 관리 기법이다.
이와 같은 방법을 통해 UAF 취약점을 방지 할 수 있다.
버그 유형 / 버퍼 오버플로우
: 일반적으로 버퍼 오버플로우는 할당된 버퍼에 데이터를 쓰거나 읽는 작업이 버퍼 경계를 초과할 때 발생 합니다.
버퍼 경계를 초과하여 접근한다는 것은 접근하면 안되는 메모리 위치를 읽거나 쓰는 작업을
하게 된다는 것을 의미 합니다.
- Stack Overflow
: 스택 영역이 힙 영역을 침범하는 경우를 스택 오버 플로어라고 한다.
- 일어나는 경우
: 종료문이 없는 무한 재귀호출 시 - Heap Overflow
: 힙 영역이 스택 영역을 침범할 경우를 힙 오버플로어라고 한다.
- 일어나는 경우
: 동적 할당을 지정된 힙 크기 보다 많이 할당 할 때
참고 사이트
https://hyo-ue4study.tistory.com/201
[CPP] 메모리 누수 찾기 - _CrtDumpMemoryLeaks()함수
위 코드는 빌드하면 아무런 문제도 없다고 나온다. 이대로 F5 디버그를 눌러봐도 문제는 없어서 정상적으로 실행된다. 하지만 해당 코드는 힙에 메모리를 할당(new)해주고 해제(delete)를 해주지 않
hyo-ue4study.tistory.com
https://woo-dev.tistory.com/84
[C++] CRT 라이브러리로 디버깅 시 메모리 누수 찾기
메모리 동적 할당 후 해제를 따로 하지 않아도 에러가 발생하지 않기에 누수 발생 여부를 알기 어렵다. 이때, CRT 라이브러리를 이용하면 다음과 같이 디버깅 시 누수 지점을 쉽게 찾을 수 있다. D
woo-dev.tistory.com
C/C++ 메모리 오류에 대하여
C에서 가장 많이 발생하는 오류가 아마도 메모리 관련 오류가 아닌가 싶은데 이는 여러가지 원인이 존재한다. 여러개의 클래스가 겹쳐지고 상속되고 난리를 치다보면 이중해제를 하는 실수는
diehard98.tistory.com
https://shayete.tistory.com/entry/7-Use-After-Free
7. Use After Free
(uaf, uaf.c 바이너리, 코드 요청하셔서 올려드립니다.) 8번째 강의는 Use After Free입니다. 말 그대로 사용한 후 해제했을 때 취약점이 일어날 수 있습니다. 정확히는 heap space에서 alloc된 공간을 free하
shayete.tistory.com
https://keyme2003.tistory.com/entry/dreamhack-uafoverwrite
[dreamhack] uaf_overwrite
개념정리 ○ UAF Use After Free, 메모리를 해제하고 다시 이용할 때 생기는 취약점이다. Use After Free(UAF) 취약점은 메모리 할당 해제 이후에도 해당 메모리를 참조하여 사용하는 보안 취약점이다. 컴
keyme2003.tistory.com
'프로그래밍(c++) > 인프런 강의 정리(C++)' 카테고리의 다른 글
강의 내용 정리(Section5 / 동적 할당 및 캐스팅 등) (0) | 2024.05.29 |
---|---|
강의 내용 정리(Section3_8/달팽이 문제) (0) | 2024.05.17 |
강의 내용 정리(Section_3/포인터, const, 참조 등) (1) | 2024.05.17 |
강의 내용 정리(Section3_5/문자열 예제 코드 분석) (0) | 2024.05.17 |
강의 내용 정리(섹션2/함수 기초, 스택 메모리와 스택 프레임) (0) | 2024.05.13 |