2010-01-21 2 views
2

연습을 위해 간단한 콘솔 Yahtzee 게임을 작성하기 시작했습니다. 이 함수가 메모리를 누설할지 여부와 관련하여 질문이 있습니다. 롤 기능은 오이스가 다시 롤 포일되어야 할 때마다 호출됩니다.C++이이 함수를 유출합니까?

동적 배열을 만드는 것입니다. 처음에는 5 개의 무작위 값을 저장합니다. 다음 실행을 위해 유지하려는 주사위를 제외한 모든 주사위를 다시 굴립니다. 나는 그 또 다른 기능을 가지고 있지만,이 문제와 관련이 없습니다 때문에 내가

주요 기능

int *kast = NULL;   //rolled dice 
int *keep_dice = NULL; //which dice to re-roll or keep 

kast = roll(kast, keep_dice); 
delete[] kast; 

그것을 왼쪽으로 여기에 기능

int *roll(int *dice, int *keep) { 

    srand((unsigned)time(0)); 
    int *arr = new int[DICE]; 
    if(!dice) 
    { 
     for(int i=0;i<DICE;i++) 
     { 

      arr[i] = (rand()%6)+1; 
      cout << arr[i] << " "; 
     } 
    } 
    else 
    { 
     for(int i=0;i<DICE;i++) 
     { 
      if(!keep[i]) 
      { 
       dice[i] = (rand()%6)+1; 
       cout << "Change "; 
      } 
      else 
      { 
       keep[i] = 0; 
       cout << "Keep "; 
      } 
     } 
     cout << endl; 
     delete[] arr; 
     arr = NULL; 
     arr = dice; 

    } 
    return arr; 
} 
+4

포인터를 삭제 한 후 포인터에 항상 NULL을 할당하라는 메시지가 표시 되었습니까? 그들은 틀렸다. –

+0

'arr = NULL; arr = 주사위;'다소 중복. :] 첫 번째 수준의 최적화만으로 빌드하면 해당 행은 컴파일 된 출력에 존재하지 않습니다. ('arr = NULL;') – GManNickG

+0

@ 스티브 : 나는 책에 대해 읽은 것을 기억한다. 무엇이 잘못 되었습니까? 나는 안전을 위해서라고 생각했다. – jasonline

답변

12

예, 누출 될 수 있습니다. 예를 들어, cout을 사용하면 예외가 발생할 수 있으며, 그렇다면 delete이 호출되지 않습니다.

동적 배열을 직접 할당하는 대신 std::vector을 반환하는 것이 좋습니다. 더 좋은 방법은 함수를 반복 알고리즘 (이 경우는 back_insert_iterator)을 사용하여 출력하는 올바른 알고리즘으로 바꾸는 것입니다.

편집 : 더 자세히 살펴보면이 코드의 기본 구조가 완전히 싫어한다는 점을 지적해야합니다. 실제로 두 가지 종류의 일을하는 한 가지 기능이 있습니다. 병렬로 주소를 지정하는 한 쌍의 배열도 있습니다. 나는 그것을 두 개의 분리 된 함수, 즉 rollre_roll으로 재구성 할 것이다. 내가 구조체의 배열로 데이터를 재구성 것 : (당신이 진정으로 주장하는 경우, 또는 배열)

struct die_roll { 
    int value; 
    bool keep; 

    die_roll() : value(0), keep(true) {} 
}; 

초기 롤을 수행하려면 초기 값을 채우는 roll 기능에 이들의 벡터를 통과 . 리 롤링을 수행하려면 벡터를 re-roll으로 전달하여 keep 멤버가 false으로 설정된 die_roll에 대해 새 값을 얻습니다.

+0

또,'auto_ptr'의 사용이 유익합니다. –

+0

Sry는 그 cout이 버그 확인에만 사용된다는 것을 언급하지 않았습니다. 어쨌든, 그 이외의 기능은 누수 방지 및 어레이 삭제 된 올바른 무엇입니까? – starcorn

+1

@klw : 그렇습니다. 메모리 할당 및 해제 사이에 예외가 발생하지 않는다면 코드에 메모리 누수가 없어야합니다. 그 상태는, 그러나, 당신의 코드가 기껏해야 예외적으로 깨지기 쉽다는 것을 의미합니다. –

4

사용 A는 (의 stack- 할당 됨) 배열 대신 std::vector을 만들고 함수에 대한 참조를 전달합니다. 그렇게하면 누출이 없는지 확신 할 수 있습니다.

+0

벡터를 사용하는 것을 고려해 봤지만, 이미 큰 목록을 알고 싶다면 배열을 사용하는 것이 더 좋을 것이라고 생각했습니다. – starcorn

+0

@klw : 무엇? 그건 말이되지 않습니다. 'std :: vector'는 코드의 표준적이고 안전한 버전입니다. 크기가 적절하지 않다는 것을 알기 때문에 벡터에서'resize' 나'reserve'를 호출하십시오. – GManNickG

+0

실제로; 재 할당이 필요 없도록 적절한 생성자를 사용한다면 그 비용을 지불하지 않아도됩니다. 아마 배열만큼 빠르며 훨씬 쉽습니다. – Thomas

4

메모리를 할당하는 방법은 혼란 스럽습니다. 함수 내에 할당 된 메모리는 함수 외부의 코드에 의해 해제되어야합니다.

왜 이런 식으로 뭔가를 다시 작성하지 :

int *kast = new int[DICE];   //rolled dice 
bool *keep_dice = new bool[DICE]; //which dice to re-roll or keep 
for (int i = 0; i < DICE; ++i) 
    keep_dice[i] = false; 

roll(kast, keep_dice); 

delete[] kast; 
delete[] keep_dice; 

이는 new의 일치와 delete 멋지게이야. 기능에 관해서는 우리가 falsekeep_dice 모두를 설정하기 때문에,도 인수 이제까지 NULL이며, 항상 새로운 배열을 반환하는 대신 dice을 수정, 그것은으로 단순화 또한

void roll(int *dice, int *keep) { 
    for(int i=0;i<DICE;i++) 
    { 
     if(keep[i]) 
     { 
      keep[i] = false; 
      cout << "Keep "; 
     } 
     else 
     { 
      dice[i] = (rand()%6)+1; 
      cout << "Change "; 
     } 
    } 
    cout << endl; 
} 

, 당신은 srand 전화를 이동해야 귀하의 프로그램 시작에. 재 시드는 무작위 적으로 매우 나쁘다.

+0

제안에 감사드립니다. – starcorn

0

제 제안은 Scott Meyers Effective C++ 3rd Edition을 사고 빌려 쓰는 것입니다. 생산적인 C++ 프로그래머가되기 위해 몇 달 간 힘들어하지 않을 것입니다. 그리고 저는 개인적이고 씁쓸한 경험에서 이야기합니다.

+0

감사합니다. – starcorn

관련 문제