Memory Leak인듯 한데요.. 소스코드 보시고 조언좀 부탁드립니다
글쓴이: rainblow / 작성시간: 일, 2004/11/07 - 2:54오후
클래스의 멤버로 가지고 있는 다른클래스의 포인터에 new로 생성한 클래스인스턴스를 할당했다가 새로운 클래스로 그값을 대치하려고 합니다.
이를 저는 linked list에서 멤버 교체할때처럼 하면 된다고 생각했는데,
메모리가 줄질 않는군요.
코드보시면 아시겠지만 destructor에 printf한값들은 전부 찍히고 있습니다..뭔가 제가 잘못이해한 부분이 있는듯 한데..
코드보시고 조언좀 부탁드립니다. 환경은 RH8.0 + gcc3.2 입니다.
아래 코드의 ⓐⓑⓒ에서의 메모리값을 top명령어로 본것을 옮겨보면
ⓐ : 24848 24M 720 S 1.7 2.4 0:00 GwMain
ⓑ : 48884 47M 720 S 1.7 4.7 0:00 GwMain
ⓒ : 48888 47M 724 S 0.0 4.7 0:00 GwMain
입니다.
제 생각으로는 delete를 한후인 ⓒ 에서는 다시 24M로 돌아와야 하는게 아닌가 하거든요.. 어디가 잘못된걸까요?
#include <iostream> #include <sys/types.h> #include <unistd.h> #include <wait.h> #include <string> #include <map> using namespace std; class GwRecord { public: GwRecord () { requestLen = 0 ; request[0] = '\0' ; resultLen = 0 ; result[0] = '\0' ; resultSepLen = 0 ; resultSep[0] = '\0' ; memset (request, 0, sizeof(request) ); memset (result, 0, sizeof(result) ); memset (resultSep, 0, sizeof(resultSep) ); printf("GwRecord constructed!! %x \n", this); } ~GwRecord() { printf(" Destructor GwRecord %x \n",this); } char request[8192]; int requestLen; char result[8192]; int resultLen; char resultSep[8192]; int resultSepLen; }; class GwServer { public: GwServer () { makeMemory(); } ~GwServer() { deleteMemory(); printf(" Destructor GwServer \n"); } }; class GwMain { public: GwServer* m_server; GwMain() { } ~GwMain() { } }; int main (int argc, char* args[]) { GwMain* Main = new GwMain(); string x; cout << "Before Make GwServer()" << endl; cin >> x; GwServer* oldServer = new GwServer (); Main->m_server = oldServer; cout << "After Make GwServer() and assign to server" << endl; //ⓐ cin >> x; GwServer* newServer = new GwServer (); cout << "After Make new GwServer()" << endl; cin >> x; GwServer* temp = Main->m_server; cout << "After assign old GwServer() to temp" << endl; cin >> x; //ⓑ Main->m_server = newServer; delete temp; cout << "After delete temp" << endl; //ⓒ cin >> x; return 0; }
Forums:
대원칙은 new와 delete의 짝이 맞아야 한다는 겁니다. 코드를 보면
대원칙은 new와 delete의 짝이 맞아야 한다는 겁니다. 코드를 보면
new는 3번 했는데 delete는 1번만 했군요. 당연히 릭이 납니다.
그리고 자원의 획득과 해제를 클래스 사용자 측에서 과도하게 부담하는
것 같습니다. 뭔가 더 좋은 방법이 있을 텐데요.
안녕하세요 지난번 비슷한 질문에도 답변주셨던분 같네요.우선 답변 감사
안녕하세요 지난번 비슷한 질문에도 답변주셨던분 같네요.
우선 답변 감사드리구요.
저 파일을 컴파일해서 돌려보면 마지막 c 에서 초기에 먹었던 a와 같은 양의 메모리를 점유하는게 아니고, 실제로 보면 b 상태의 메모리를 그대로 유지합니다.
말씀하신것처럼 new와 delete는 쌍을 이루어야 하지만, 목적상 메모리상에 클래스객체 한개는 항상 유지하고자 하는 목적이거든요.
요약을 하면
1. new -> 24M 메모리 생성.
2. 또 new -> 24*2 => 48M 메모리 점유
3. 먼저 생성한 놈 delete => 24M로 메모리 감소
가 정상일듯 한데 여전히 48M를 가진다는 것이죠.
문제는 바로 요점입니다. 이게 24M로 줄어야 정상이겠죠.
저는 GwRecord가 생성되어 점유되는 메모리에 관심있어서 테스트를 하는 중이라 GwMain같은 놈은 delete안했습니다만, 이건 일단 논외로 하구요..
님께서 일전에 답장주신대로 boost를 쓸려고 해도 이게 제가 첨부터 코딩한게 아니라서 고친다는것 자체가 부담이고, 현재 있는 문제점 자체가 궁금해서.. 그냥 모르는채로 넘어가긴 힘드네요.
한번만 더 짚어주시면 감사하겠습니다.
delete 후에 메모리를 OS에 돌려줘야 하는 건 아닙니다. 라이브러리
delete 후에 메모리를 OS에 돌려줘야 하는 건 아닙니다. 라이브러리가 가지고 있다가 다음번 new 할당 때에 쓸 수 있습니다. (대개 그러고요.)
http://valgrind.kde.org/faq.html4.3
http://valgrind.kde.org/faq.html
4.3 참고하십시오.
[quote="cdpark"]delete 후에 메모리를 OS에 돌려줘야
라이브러리 자체에서 따로 메모리 관리 정책을 쓰지 않는 한 delete를 하면
OS로 회수되어야 하는 거 아닌가요? 저도 이 점은 확실히 모르겠습니다.
이런 이유가 아니라면 GwServer의 소멸자가 가장 혐의가 짙군요.
makeMemory()와 deleteMemory()가 제대로 동작하는지 살펴보세요.
[code:1]classGwServer {public&#
네 제가 생각하기에도 라이브러리에서 메모리를 가지고 있는다는건 좀..
보통 자바나 닷넷의 경우에는 버추얼머신에서 메모리관리를 하니까 그럴수 있다고 하지만, 이경우는 좀 다르지 않나 하는 생각입니다.
제가 코드를 붙여넣으면서 빼먹었더군요.
GwServer의 제대로된 클래스소스는 위와 같습니다.
소스를 실행시켜보면 GwServer의 소멸자에서 deleteMemory를 호출하고 여기서 delete를 호출하는데 따라서 GwRecord의 소멸자가 전부 호출되고 있습니다. 생성자에서 찍은 메모리 주소와도 1:1로 맵핑이 되고요..
고수님들의 의견 부탁드립니다.
[quote]4.3. My program uses the C++ STL
위에 어느분이 링크를 걸어주신 부분에서 해당하는 부분을 읽어봤습니다.
이게 사실이라면 제가 그동안 잘못알아왔던것이 맞겠네요
STL같은 라이브러리 차원에서 메모리를 풀링한다..
참.. 어색한 개념입니다만..
그렇다면 제가 몇일동안 고생한게 보람이 없어지는 허탈한 경우네요..
보통 메모리 체크는 어떤 방법으로 하세요?
저처럼 top명령어로 하시지는 않는가보죠?
이건 지금과는 좀 다른 얘기 같습니다. 그러니까vector<
이건 지금과는 좀 다른 얘기 같습니다. 그러니까
vector<int> v;
v.clear();
에서 clear()를 해도 v가 갖고 있던 메모리가 바로 해제되지는 않는다는 얘깁니다.
allocator로 메모리 관리를 제어할 수 있는 길을 열어 두고는 있긴 하지만요.
지금처럼 날포인터(raw pointer)로 직접 해제하는 것과는 다르지요.
혹시 GwServer의 map을 생각하고 계실지 모르겠는데 그것도 GwServer의
소멸자가 끝나면 map 개체 자체도 소멸되므로 당연히 메모리가 회수되어야
합니다.
그런데 올리신 코드를 WinXP에서 .NET과 gcc로 해봤는데 잘 되는데요? :)
(c)에서 24M의 메모리가 회수되는 것을 확인했습니다.
[quote="doldori"]이건 지금과는 좀 다른 얘기 같습니다. 그
전 C++는 잘 모릅니다만, Spec에 raw pointer를 delete하면, 메모리가 확실히 반환된다라고 되어 있지 않는다면, STL이 아니라 raw pointer로 delete한다고 해도 반환될지는 확실히 보장 못할 것 같습니다만.(gcc와 visual C++에선 된다고 해도) STL까지 가지 않고서도, 스펙이 강제하지 않는다면 new, delete도 메모리를 재활용할 수 있을듯 싶습니다.
이유는 모르겠지만 순간적인 반환상태가 그렇게 중요하다면 system call정도를 믿을 수 있지 않을까 생각됩니다.
--
Life is short. damn short...
[quote="jj"]전 C++는 잘 모릅니다만, Spec에 raw po
맞는 말씀입니다. 표준에서 메모리 회수 시점을 강제하는 구절은 찾지 못했습니다.
저의 이전 포스팅은 정확하지 않음을 사과드립니다.
저는 RedHat8.0 에서 GCC3.2버전으로 테스트 했습니다만,확
저는 RedHat8.0 에서 GCC3.2버전으로 테스트 했습니다만,
확실히 c 에서 24M가 반환되지 않습니다.
운영체제에 따른 영향이라고 밖에는 볼수가 없겠군요.
RH9.0 시스템에 있는데 그곳에서 해봐도 같은 결과군요...
쩝.. 운영체제에 따른 문제일까요? ㅡㅡ;;
추신 : 바로 윗글을 읽지 못했군요. Spec에 그런 부분이 없다면 메모리가 재활용될수도 있는거군요.. 많은걸 배웁니다.
댓글 달기