본글은 최근에 Pwnable 문제중 C언어, Python뿐만 아니라 C++로 이루이진 문제를 접하는 경우가 많아져서 Python, Java와 다른 C++만의 문법이나 차이점등을 정리하기 위해 작성한 글입니다.
잘못된 부분이 있다면 댓글로 알려주시기 바랍니다.
(예시 코드등은 TCP 스쿨의 자료를 참고했습니다.)
https://www.tcpschool.com/cpp/intro
1. C++ 메모리 동적 할당
C에서 메모리 동적할당에 사용되는 라이브러리 함수 malloc()등이 있다.
C++에서도 마찬가지로 라이브러리 함수를 사용하기 때문에 malloc()으로 할당하거나 free()로 할당된 메모리의 해제하는 것이 가능하다.
그러나, C++은 라이브러리 함수 보다 효과적인 동적 할당 및 해제를 위해 new 연산자와 delete 연산자를 추가해 사용한다.
아래의 코드는 기존에 사용하던 라이브러리 함수인 malloc()과 new의 문법이다.
// C
int *p = (int *)malloc(sizeof(int));
int *p = (int *)malloc(sizeof(int) *10); //malloc(40)
// C++
int *p = new int;
int *p = new int[10]; // == malloc(40)
// 사용자 정의 데이터형
include <iostream>
class A {
public:
A(int a, int b) {
int c = a * b;
}
};
struct B {
int a;
int b;
};
int main(void) {
int * ptr1 = new int(123);
A * ptr2 = new A(1, 2);
B * ptr3 = new B({ 1,2 });
std::cout << ptr3->a << " " << ptr3->b;
}
malloc을 사용할 때보다 new 연산자를 사용할때 형 변환등이 없어 코드가 훨씬 간결해 가독성이 좋아졌다.
그래서 대부분 new 연산자를 많이 사용한다고 한다.
기존에 사용하던 malloc은 함수, 그중에서도 라이브러리 함수이다. C가 만들어진 이후 추가적으로 만들어진 함수이기 때문에 malloc 함수와 컴파일러간에 문법적으로 약속된게 없어 개발자가 매개변수나 형 변환, sizeof등을 추가해 사용할 수 밖에 없었다.
C++에서는 이러한 문제를 연산자로 문법 형식을 약속했기 때문에 약속된 문법을 사용하면 정해진 방식으로 처리를 해주어 단순한 문법으로 표현이 가능한 것이다.
new 사용시 주의점
new 연산자가 편리하긴 하지만 malloc이나 calloc과는 차이점이 있기에 사용시 유의해야할 점이 있다.
new연산자는 메모리의 크기를 정하지 않는다. malloc에서는 sizeof를 통해 정의했다면 new에서는 다음과 같다.
주소를 지정할 포인터 = new 할당하고 싶은 크기의 자료형;
이때 뒷부분에 오는 데이터형을 예시로 int를 사용했으나 해당 부분에 "데이터형" 이기만 하면 상관없이 모두 가능하다.
즉, 사용자 정의 데이터형이어도 new 연산자를 사용하면 해당 데이터형의 크기를 파악하고 크기만큼 메모리 공간을 할당해 주소를 리턴한다.
(예시 코드를 보면 사용자 정의 데이터형인 A나 B를 사용한 new 코드를 확인 할 수 있다. 단, 구조체를 사용할때는 { }로 감싸 사용해야 한다.)
2. C++ 메모리 동적 해제
C++에서 동적 메모리 할당을 했다면 해제또한 진행해야 한다. 기존 C에서는 free()함수를 사용해서 메모리를 해제했으나 C++에서는 delete 연산자를 사용하게 된다. (물론 free()함수를 그대로 사용하는 것도 가능하다. )
// C
free(p);
// C++
delete p;
delete 연산자는 free와 문법에서도 크게 차이나지 않아 개선된 부분이 적어 필요성이 떨어져 보이지만 new 연산자와 쌍으로 쓰이기 때문에 new 연산자를 사용했다면 delete 연산자로 할당된 메모리를 해제해야 한다.
(메모리 해제이기 때문에 malloc을 사용하고 delete로 해제하거나 new 할당후 free로 해제해도 에러가 발생하지 않으나 이렇게 사용해도 된다는 뜻은 아니다.)
delete 사용시 주의점
delete는 사용시 단순하게 메모리가 할당되었는지, 그룹 형식으로 메모리가 할당되었는지에 따라 사용방법에 차이가 있다.
int *p = new int;
...
delete p;
int *p = new int[10];
...
delete[] p;
단순하게 메모리가 할당되었다면 그대로 해제하면 되지만 그룹형식으로 할당되었다면 해제시에도 이를 표기하지 않으면
오류가 발생하게 된다.
이외에도 delete로 해제하는 포인터가 널 포인트인 경우에는 사용시 아무런 문제가 없으나 할당된 메모리 공간을 free를 두번 해제하여 발생하는 Double free bug가 delete에서는 보호되어 있어 두번 해제하게 되는 경우 오류를 발생시키게 되어있다.
Reference
1. https://www.tcpschool.com/cpp/cpp_arrayPointer_malloc
2. https://blog.plorence.dev/510
'Reference > Language_Study' 카테고리의 다른 글
[C++] 5. C++ 프렌드(friend), 스마트 포인터(smart pointer) (0) | 2024.03.25 |
---|---|
[C++] 4. C++ 참조자(reference), 소멸자(destructor) (2) | 2024.03.25 |
[C++] 2. C++ typeid, endl 과 \n 차이 (0) | 2024.03.19 |
[C++] 1. C++ nullptr, namespace (0) | 2024.03.18 |
명품 JAVA 에센셜 6장 실습문제 (0) | 2022.06.14 |