2013-03-18 3 views
0
struct Package_Node 
    { 
     int bar_code; 
     float package_weight; 
     Package_Node *next_packaged; 
    }; 

    struct Key_Node 
    { 
     int key; 
     Package_Node *next_package; 
    };   

    for(int i=0; i<3; i++) 
      { 
       if(keyMain[i].next_package==NULL) 
       { 
        continue; 
       } 

       if(keyMain[i].next_package!=NULL) 
       { 
        nPointer3=keyMain[i].next_package; 
        nPointer4=keyMain[i].next_package; 
        while(nPointer3) 
        { 
         nPointer4=nPointer4->next_packaged; 
         delete[] nPointer3; 
         nPointer3=nPointer4; 
        } 
       } 
      } 

keyMain 주어진 구조체 key_node에 의해 기술 된 배열.동적 연결 목록을 삭제하는 데 문제가 있습니까?

키 메인 자체는 동적 배열이지만 코드의 경우 정적 배열로 표시되었습니다.

배열은 3 개의 색인 길이가 길고, 0,1,2이고 각 색인에는 별도의 연결 목록이 포함되어 있습니다. 이제 각 링크 된 목록을 삭제하려고하지만 일부는 삭제되고 나머지는 그렇지 않은 것처럼 보입니다.

어떻게이 문제를 해결할 수 있습니까?

+0

nPointer3에서 가리키는 메모리가 할당 된 행을 표시 할 수 있습니까? – Digikata

+0

'Package_Node' 엘리먼트에'delete []'를 사용하는 이유는 무엇입니까? 배열 인 경우 나머지 배열은 어떻게됩니까? –

+0

@ChrisDodd'Package_Node'는 배열이 아닙니다. 연결된 목록입니다. 그러나 Key_node는 배열입니다. –

답변

1

여기서 무엇을 잘못하고 있습니까? 하나는 수동으로 메모리를 관리하는 것입니다.

#include <memory> 

struct Package_Node 
{ 
    int bar_code; 
    float package_weight; 
    std::unique_ptr<Package_Node> next_packaged; 
}; 

struct Key_Node 
{ 
    int key; 
    std::unique_ptr<Package_Node> next_package; 
}; 

reset(new Package_Node())을 사용합니다 unique_ptr에 대한 포인터를 저장합니다. delete 대신 reset()으로 전화하십시오. unique_ptr이 가리키는 항목은 unique_ptr이 삭제되면 자동으로 삭제됩니다.

이것은 C++ 11 - C++ 03의 경우 std::tr1::unique_ptr 또는 boost::unique_ptr 일 수 있지만 이동 의미가없는 경우 unique_ptr은 사용하기가 더 위험합니다. 위의 할 경우


지금, 당신의 코드는 훨씬 짧은되고, 전체 연결리스트를 할당 해제하는 .reset() 첫 번째 노드에 스마트 포인터의 문제입니다 : 다른 모든이 자동으로 삭제됩니다!

그러나이 작업을 수행하지 않을 수도 있습니다. 따라서 코드에서 다른 문제를 공격 할 것입니다.

변수 이름에 값의 사용이 반영되지 않습니다. nPointer4은 끔찍한 변수 이름입니다. 그 목적이 무엇인지 문서화하는 PointerToDelete을 시도하십시오. 또한 초기화 시점에서 포인터를 선언하고 포인터를 사용 전후에 처리하지 말고 유효하지 않은 순간에 포인터를 지워야합니다. (변수를 재사용 할 때 보너스 포인트가 없습니다.) nPointer3nPointer4while의 시작에 동일한 데이터를 유지해야

  nPointer3=keyMain[i].next_package; 
      nPointer4=keyMain[i].next_package; 
      while(nPointer3) 
      { 
       nPointer4=nPointer4->next_packaged; 
       delete[] nPointer3; 
       nPointer3=nPointer4; 
      } 

노트, 왜 그들은 모두 존재 :

이 루프를 보면? 이 같은 재 작성하여 상태를 반으로 줄일 수있다 : ptrToDelete 만이 초기화되는 순간에 존재하는 방법

  Package_Node* ptrToDelete=keyMain[i].next_package; 
      while(ptrToDelete) 
      { 
       Package_Node* nextPtr = ptrToDelete->next_packaged; 
       delete ptrToDelete; 
       ptrToDelete = nextPtr; 
      } 

알 수 있습니다.

가능한 한 짧은 시간에 nextPtr이 존재하고 범위를 벗어납니다. 또한 초기화 된 후에 만 ​​존재합니다.

다음으로 항상 문제를 실제로 보여주는 컴파일 코드를 게시하십시오. 위의 코드는 문제와 전혀 관련이없는 이유로 컴파일되지 않으며 마음을 읽는 것은 사람들에게해야 할 일이 아닙니다.

무엇이 잘못되었는지를 모르는 것이므로 무엇이 중요하거나 중요하지 않은지 어떻게 알 수 있습니까?Easy : 컴파일러가 알아낼 수 있도록하십시오. 문제를 보여주고 컴파일하고 문제가 계속 발생하는지 테스트 한 간단한 예제를 작성한 다음 인 게시하십시오.

문제가있는 대신 부품을 제거하여 짧게 만들거나 문제가 있거나 그렇지 않을 수도있는 컴파일되지 않는 코드를 게시하고 다른 사람들이 마음을 읽을 수 있기를 바랍니다.

struct Package_Node*의 사용은 완전히 불필요합니다. Package_Node*은 더 짧으며 (극단적 인 일부 경우는 제외) 완전히 똑같습니다.

똑똑한 포인터를 사용하지 않더라도 포인터를 소유 한 struct은 소멸자에서 포인터를 소유해야하며 그렇지 않은 경우 다른 포인터가 있어야합니다. RAII 님은 친구입니다. 포인터를 소유 한 struct을 만들 때 rule of three을 따르는 것을 잊지 마십시오.

+0

여기서 수동으로 메모리를 관리하지 않습니다. 방금 코드를 위해 설명서를 사용했습니다. –

+0

전체 프로그램은 약 700 줄이며, 주어진'structs'를 사용하여 전체 프로그램을 수행했습니다. 이 문제를 해결할 다른 방법이 있습니까? 또한이 프로젝트는 학교 프로젝트이므로 주어진 struct에 충실해야합니다. –

+1

@QaziHossain 의미가 없습니다. "저는 수동으로 메모리를 관리하지 않습니다."와 "나는 수동으로 사용했습니다."- 수동으로 메모리를 관리하고 있거나 그렇지 않습니다. – Yakk

1

어떻게 삭제되었는지 확인하는 방법을 모르겠습니다. 일단 메모리를 할당 해제하면 그 메모리는 재사용 될 수 있고 더 이상 액세스 할 수 없습니다. 런타임 오류가 발생하지 않는 한 아무도 멈추지는 못하지만 메모리의 내용은 할당 해제에 의해 수정되지 않습니다.
검사를 통해 특정 개체의 할당이 해제되었음을 알릴 수 없습니다.

작업을 완료하면 keyMain[i].next_package을 (를) NULL (으)로 설정하는 것을 잊었습니다.

for(int i = 0; i < 3; i++) 
{ 
    if (keyMain[i].next_package != NULL) 
    { 
     Package_Node* current = keyMain[i].next_package; 
     Package_Node* next = 0; 
     while (current) 
     { 
      next = current->next_package; 
      // No "[]" since you're apparently not allocating with "[]" 
      delete current; 
      current = next; 
     } 
     keyMain[i].next_package = NULL; 
    } 
} 
+0

'keyMain [i] .next_package'를 두 번 삭제합니다 - 루프의 첫 번째 반복에서'delete []'를 사용하고 두 번째로 루프 –

+0

다음에'delete'를 사용하여 두 번째 삭제하면 모든 것이 옳다고 말하고 있습니다 'key_node' 내의 각 포인터를 null로 설정해야합니까? –

+0

@ChrisDodd 그 점을 발견해 주셔서 감사합니다. – molbdnilo

1

nPointer3 메모리가 "new Package_Node"를 통해 할당되었다고 언급 했으므로 "delete [] nPointer3;" 읽어야합니다 :

delete nPointer3; 
nPointer3 = NULL; // recommended (mentioned in another answer) 

설명하는 동작은 단일 new를 통해 할당 된 nPointer3 메모리를 해제하려고 시도 할 때 정의되지 않은 동작이 발생할 수 있습니다. 배열 new 연산자 "new []"(예 : new Package_Node [16])를 통해 할당 된 메모리 만 "delete []"와 함께 릴리스되어야합니다.