반응형
출처 : http://kuaaan.tistory.com/trackback/142
delete와 delete[], new와 new[]를 구분해서 사용해야 하는 이유 :
delete를 사용하든 delete[]를 사용하든 메모리는 정상적으로 해제된다. 하지만 4바이트 INT 타입의 10개짜리 Array를 메모리해제할 경우 delete[]를 사용하면 4바이트씩 10번 해제하지만 delete를 사용하면 40바이트짜리 메모리를 한번 해제한다.
내부적으로 얘기하자면 new[] 를 사용할 경우 할당하는 메모리 앞에 4바이트 메모리를 더 할당하여 배열의 Size를 저장해놓는다. 이 메모리를 해제할 때 delete[]를 사용하면 이 값(배열의 Size)을 확인하지만 delete를 사용하면 확인하지 않는다. 따라서 delete[]를 사용해야 Array가 Class Type Array인 경우 각각의 Entry에 대해 배열의 Size만큼의 생성자/소멸자를 호출해 줄 수 있다.
http://minjang.egloos.com/1414494요약하면, class array를 메모리 해제할때 delete[]를 사용하지 않고 그냥 delete를 사용할 경우 소멸자가 한번만 호출되어버리는 문제가 발생한다.
실제로 테스트를 해보니 맞다. ^^
- class CTest
- {
- public:
- CTest()
- {
- printf("Constructer(0x%08x)\r\n", this);
- }
- ~CTest()
- {
- printf("Destructor(0x%08x)\r\n", this);
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CTest* pTest = new CTest[10];
- delete pTest; // 여기!!
- // delete[] pTest;
- return 0;
- }
위와 같은 소스코드를 실행시키면 다음과 같이 된다.
Constructer(0x003e3c1c)
Constructer(0x003e3c1d)
Constructer(0x003e3c1e)
Constructer(0x003e3c1f)
Constructer(0x003e3c20)
Constructer(0x003e3c21)
Constructer(0x003e3c22)
Constructer(0x003e3c23)
Constructer(0x003e3c24)
Constructer(0x003e3c25)
Destructor(0x003e3c1c)
계속하려면 아무 키나 누르십시오 . . .
Constructer(0x003e3c1d)
Constructer(0x003e3c1e)
Constructer(0x003e3c1f)
Constructer(0x003e3c20)
Constructer(0x003e3c21)
Constructer(0x003e3c22)
Constructer(0x003e3c23)
Constructer(0x003e3c24)
Constructer(0x003e3c25)
Destructor(0x003e3c1c)
계속하려면 아무 키나 누르십시오 . . .
10개의 인스턴스가 해제되었는데, 소멸자는 한번만 호출되었음을 알 수 있다.
만약 소멸자에서 해제해 주는 메모리나 리소스가 있었다면 9개씩의 Leak이 발생했을 것이다.
delete를 delete[]로 수정해주고 나니 아래와 같이 정상적으로 소멸자가 호출된다.
Constructer(0x003e3c1c)
Constructer(0x003e3c1d)
Constructer(0x003e3c1e)
Constructer(0x003e3c1f)
Constructer(0x003e3c20)
Constructer(0x003e3c21)
Constructer(0x003e3c22)
Constructer(0x003e3c23)
Constructer(0x003e3c24)
Constructer(0x003e3c25)
Destructor(0x003e3c25)
Destructor(0x003e3c24)
Destructor(0x003e3c23)
Destructor(0x003e3c22)
Destructor(0x003e3c21)
Destructor(0x003e3c20)
Destructor(0x003e3c1f)
Destructor(0x003e3c1e)
Destructor(0x003e3c1d)
Destructor(0x003e3c1c)
계속하려면 아무 키나 누르십시오 . . .
Constructer(0x003e3c1d)
Constructer(0x003e3c1e)
Constructer(0x003e3c1f)
Constructer(0x003e3c20)
Constructer(0x003e3c21)
Constructer(0x003e3c22)
Constructer(0x003e3c23)
Constructer(0x003e3c24)
Constructer(0x003e3c25)
Destructor(0x003e3c25)
Destructor(0x003e3c24)
Destructor(0x003e3c23)
Destructor(0x003e3c22)
Destructor(0x003e3c21)
Destructor(0x003e3c20)
Destructor(0x003e3c1f)
Destructor(0x003e3c1e)
Destructor(0x003e3c1d)
Destructor(0x003e3c1c)
계속하려면 아무 키나 누르십시오 . . .
아 그렇군. ^^
반응형
'Coding Tip > C/C++' 카테고리의 다른 글
Blocking/Non Blocking Socket 관련 참고자료 (1) | 2016.12.03 |
---|---|
new 연산자를 사용한 동적 메모리 할당 실패시 예외 처리 (0) | 2015.06.18 |
[System Call] 메모리 맵 - mmap(), munmap(), msync(), CreateFileMapping, MapViewOfFile, UnmapViewOfFile (0) | 2015.05.14 |
gcc 컴파일 옵션 정리 (2) | 2015.04.17 |
C/C++ Socket에서 비동기 connect 처리하기 (0) | 2014.05.16 |