STL사용시 메모리 해제 문제
글쓴이: syia / 작성시간: 금, 2008/05/23 - 10:57오전
STL에서 hash_set을 사용하고 있는데,
객체를 따로 할당해서 포인터를 넣어서 쓰고있습니다.
때문에 이걸 해제 해줄 필요가 있는데,
문제는 해제하는 방법입니다.
아래 코드는 정상적이라고 생각되지만 이중 메모리 해제 경고가 뜨면서 프로그램이 종료되더군요
it는 이터레이터 이고, white는 hash_set입니다.
for(it = white.begin(); it != white.end(); it++) { delete *it; }
it++ 처럼 표기하는것 보다 ++it로 표기하는것이 안전하다해서 해봤지만 아래코드도 제대로 안되더군요.
for(it = white.begin(); it != white.end(); ++it) { delete *it; }
제대로 동작하는건 아래처럼 했을때였습니다.
for(it = white.begin(); it != white.end(); ) { delete *it++; }
대체 왜 이런지 전혀 알수가 없더군요.
대부분의 문서에서도 위의 두가지 방법을 사용하던데,
어째서 위의 두가지 경우는 이중 메모리 해제 문제가 발생할까요?
혹시나 해서 메모리 주소를 찍어봤더니 같은 메모리 공간을 다시 해제하려 하더군요.
예를들어 처음엔 0x0001 이었다면 그담엔 0x0349 그담엔 다시 0x0001 을 해제하려 했었습니다.
2.6.9-55 커널에 g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-8)을 사용했습니다.
Forums:
위의 1번째 2번째는...
위의 1번째 2번째는... it 이 가리키는 곳의 메모리를 해제 한 뒤에.. 다시 it 을 사용해서 무언가 일을 하려다 보니까.. 문제가 있어보이구요..
3번째는 왜 정상적인지는 모르겠지만... 1,2,3 모두 불안해 보입니다.
해제 하려는 포인터 뒤에 참고하는 부분을 미리 copy 한 다음에 쓰는게 어떨까 싶습니다.
delte it; 대신에..
뭐 그런식으로 해서 다음번 해제할 곳을 저장해 둬야 되지 싶네요..
뒤에 참고할부분을 카피하려면
가 되야겠지요
에고..죄송합니다....
에고..죄송합니다....
저도 질문을 가끔 하는 편이라서.... 질문자의 마음을 아는데도... 그 마음을 생각도 않고..건성건성 읽고 답글을 달았네요..
죄송합니다. (..;) 쥐구멍에라도 숨고 싶군요... (답변에 익숙치 않아서 그러니 이해 부탁드립니다 )
아..질문 주신 내용을 이제 보고 이해했네요...그리고 제가 달은 답도 이상하고;;;
저도 한번 해봐야겠습니다...
p.s 위에 내용도 ... delete 하면.. j 는 it + 1 이 되지만 it 도 변하니까.. 결국 j 가 delete 되는 거 같네요..
^^
관심갖고 봐주셔서 감사하구요 ^^;
delete할때 j 를 하는게 아니라 *j 를 하기때문에 j자체가가지는 값은 변하지 않을겁니다.
실제 it의 값이 변하는것은 아니니 문제가 없어야 하지 않을까요
it가 100번지에 있고
100번지에 있는 값이 4000 이고
delete하는것은 4000 번지니까요
delete후에도 it 는 여전히 100번지에 있고
4000 이라는 값이 들어있겠지요.
그래서 1,2번째도 문제가 될게 없다고 생각했습니다.
코드를 조금 수정해서 문자열이 있는 곳의 주소를 카피해서 해제해 보았습니다.
이코드도 마찬가지로 이중메모리 해제 에러가 납니다.
it++로 하느냐 ++it로
it++로 하느냐 ++it로 하느냐는, 안전하고 아니고의 문제가 아니라 성능문제입니다.
it++는 임시객체 만들어 반환하기 때문이죠.
그보다, 메모리 해제문제는 할당하는 부분부터 보지 않으면 알기 힘든 내용입니다.
예를 들면 애시당초 똑같은 포인터가 해쉬에 두개들어가있을지도 모르는 것이죠.
혹은 중간에 실제로 다른 곳에서 해제를 하고 있을지도 모르구요.
그러니 중간에 따로 삭제하거나 재 할당하는 부분이 있다면 그부분도 포함하여, 해쉬를 초기화하고 메모리 할당하고 해제하는 부분까지의 일련의 코드를 봐야 답을 알수 있을듯합니다.
가능성은 가장 낮겠지만, hash_set은 표준 STL에는 들어있지 않으므로, 3rd파티의 STL을 쓰신다는 뜻인데, 그 라이브러리 자체의 결함일수도 있겠구요...뭐 이건 임시로 hash_set을 표준 STL의 set으로 바꿔서 똑같은 에러가 나는지 확인해보면 쉽게 알수 있지만요.
음...
할당은 new로 문자열 길이만큼 할당을 해서
포인터를 white.insert() 를 통해서 넣었구요.
처럼 선언해서 eqstr함수에다가 문자열간 크기 비교할수 있도록 넣었습니다.
printf로 찍어보면 정상적으로 나오니 똑같은 포인터에 두개가 들어가거나 하는일은 없을겁니다.
중간에 해제도 한게 아니구요.
음.. 표준 STL이 아니라서 버그가 있을 가능성이 제일 높은것 같구요.
다른데서 좀 찾아본것도, hash_set에서는 포인터를 통한 객체 보관은 하지 않는걸 권장하더군요.
표준 STL의 set에선 정상동작을 합니다.
해봤는데 아무 문제
해봤는데 아무 문제 없는데요...
환경은..
Ubuntu 8.04
g++ (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
stlport 5.1
컴파일 명령은..
g++ -Wall -O0 -ggdb3 -I/usr/include/stlport -pthread -lstlport -o a a.cpp
음.. gcc 버전의 문제인것 같네요
작성해주신 소스도 거의 같군요.
소중한 댓글 감사합니다.
컴파일러 버전을 바꿔보아야겠네요 ^^;
댓글 달기