stl에서 new, delete 문제

이찬범의 이미지

class Frame
{
public:
Frame(void);
Frame(int frameNo) {score = new int[2]}; //다른 기능 생략...
~Frame(void);

int *score;
};

class Game
{
public:
Game(void) {currentFrame = newFrame()}
~Game(void){
for(list::iterator it = frames.begin(); it != frames.end();)
{
frames.erase(it++);;
}
}

Frame *currentFrame;
list frames;

Frame* newFrame(void);
bool throwDown(int pinCount);
};

Frame* Game::newFrame(void)
{
Frame *f = new Frame(currentFrameNo);
return f;
}

bool Game::throwDown(int pinCount)
{
if(pinCount < 0 || pinCount > 10)
{
return false;
}
if(!currentFrame->AddScore(pinCount))
{
return false;
}
checkFrameBonus(pinCount);
if(isNextFrame(pinCount))
{
currentFrameNo++;
[b]frames.push_back((Frame&)*currentFrame);
currentFrame = newFrame();
}
return true;
}

볼링 게임을 만드는 중인데 Game클래스의 멤버로 list을 가지고 Frame 객체를 throwDown함수에서 push_back했습니다.

new를 이용해서 Frame 객체를 할당한 이유는 local 변수로 할당해서 list에 추가하는 경우 그 함수가 끝나면 stack에서

사라지기 때문입니다.(제가 잘못 생각하는 경우일 수도 있는데 혹시 stl에 특정 함수내에서 지역변수로 할당한 객체를 삽입할 경우

다른 함수에서 사용이 가능한가요? 저는 stack이 사라지기 때문에 안될 것이라고 생각해서 위와 같이 했습니다.)

근데 정작 문제는 destructor에서 발생하네요. 위와 같이 파괴자를 작성하니 memory leak이 발생하는 것 같아서

Frame* fr = (Frame*)&it;
frames.erase(it++);
delete fr;

로 파괴자의 루프안을 수정하면 이중 해제로 에러가 발생합니다.

문제를 어떻게 해결해야 할까요?

ps 끝까지 읽어주셔서 감사합니다.

JuEUS-U의 이미지

delete fr 부분에서 로컬변수인 it가 지워지게되는 것 아닌가요..?
함수 끝나면서 자동으로 파기될 때 에러가 뜨는게 아닌가 싶습니다.

klara의 이미지

Frame* fr = (Frame*)&it;
frames.erase(it++);
delete fr;
이건 잘못된 변환입니다. it는 어디까지나 반복자이지 컨테이너 내용물 그자체가 아닙니다. &it는 반복자의 주소이지, 그 내용물이 아닙니다. C형식의 캐스팅이 얼마나 위험한지를 알수 있지요.
지금 지우고있는 것은 반복자 그자체일 뿐만 아니라, 잘못된 형변환으로 인해 소멸자조차 제대로 호출될수 없는 상태입니다.

이찬범의 이미지

계속 찾아보고 있는데 문제는 frames.push_back((Frame&)*currentFrame); 이 부분에서도 문제가 발생하여

제대로 list에 삽입되지 못하고 있습니다.

어떤 식으로 해결해야 할가요?

klara의 이미지

복사 생성자 및 대입연산자를 적절하게 구현해보세요.
STL은 모든 객체를 복사해서 집어넣습니다. 동적할당한 녀석을 집어 넣는다고 그녀석이 들어가는게 아니라 = 로 그녀석을 복사해서 집어넣게 됩니다.(복사생성자를 쓰는지 대입연산자를 쓰는지 기억이안나네요).
지금 Frame의 멤버가 포인터이기때문에 복사생성자나 대입연산자없이 복사를 하면 얕은 복사만 이루어지게됩니다.
소스가 읽기 힘들어서 안봤습니다만, 이런 문제라면 Frame의 동적할당은 필요가 없네요.

이찬범의 이미지

Frame::Frame(const Frame& frame)
{
frameNo = frame.frameNo;
throwCount = frame.throwCount;
bonusCount = frame.bonusCount;
frameScore = frame.frameScore;
if(frameNo != 10)
{
score = new int[OTHER_FRAME];
}
else
{
score = new int[TEN_FRAME];
}
*score = *(frame.score);
}

Frame operator =(const Frame& frame)
{
frameNo = frame.frameNo;
throwCount = frame.throwCount;
bonusCount = frame.bonusCount;
frameScore = frame.frameScore;
if(score == NULL)
{
if(frameNo != 10)
{
score = new int[OTHER_FRAME];
}
else
{
score = new int[TEN_FRAME];
}
}
*score = *(frame.score);
}

다음과 같이 복사 생성자와 = operator 오버로딩 했습니다. 위 소스에 문제가 있는건가요?

klara의 이미지

구현그자체는 문제없어보이네요.
*score = *(frame.score);
이게 의도한 바인지는 모르겠습니다만, 이걸로 런타임이나 컴파일시에 에러가 나진 않을테구요..
그리고 긴 코드를 올리실때는 code로 감싸서 적절하게 들여쓰기를 해주세요.
마지막으로 '문제가 된다'고 하셨는데 무슨 문제인가요?

이찬범의 이미지

말씀하신 부분은 제가 실수한 부분이라 다음과 같이 수정하였습니다.

for(int i=0; i {
score[i] = frame.score[i];
}

그런대도 해결되지 않네요

auditory의 이미지

코드는 코드블럭 안에 넣어주세요..
코드가 깨져서 frame의 타입을 어떻게 하셨는지 모르겠지만,
아마도

list<Frame*> frame

으로 했다면 별도의 대입 및 복사 연산자가 필요없습니다. 대신 메모리 관리는 직접 해야지요.
넣을때 포인터를 넣고..
Frame* currentFrame = new Frame;
insert(currentFrame)

지울때
for (it=frame.begin(); it!=frame.end(); it++)
    delete *it

로 해야겠죠.

물론

list<Frame> frame

로해서 개체 자체를 넣을수도 있습니다. 이경우 넣는 순간 복사가 되어
리스트에 들어가므로 local변수가 지워질 문제는 없습니다.
대신 복사가 되는거니, 복사 연산자가 있어야겠지요.
이경우 frame이 없어질때
각각의 개체들도 없어집니다. 물론 따로따로 소멸자를 호출하면서요.
klara의 이미지

Quote:
볼링 게임을 만드는 중인데 Game클래스의 멤버로 list을 가지고 Frame 객체를 throwDown함수에서 push_back했습니다.

new를 이용해서 Frame 객체를 할당한 이유는 local 변수로 할당해서 list에 추가하는 경우 그 함수가 끝나면 stack에서

사라지기 때문입니다.(제가 잘못 생각하는 경우일 수도 있는데 혹시 stl에 특정 함수내에서 지역변수로 할당한 객체를 삽입할 경우

다른 함수에서 사용이 가능한가요? 저는 stack이 사라지기 때문에 안될 것이라고 생각해서 위와 같이 했습니다.)


위에도 적었지만, list에 추가될떄는 무조건 복사되어서 추가됩니다.
그렇기 때문에, 원래 객체가 스택에 있던 힙에 있던 상관없고, list내의 객체가 사라지는 것은 해당 list가 사라질때입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.