2014-10-16 68 views
0

我已經編寫了一個代碼,用於從單個鏈接列表中刪除節點a。我測試過這段代碼,輸出很好。我對這段代碼中最後的「else」塊有些困惑。這是對的嗎? 我的意思是,釋放(p-> ptr)節點後,我仍然可以訪問它旁邊的節點嗎?這段代碼是否正確地從鏈表中刪除節點?

NODE* delNODE(NODE *HEAD,int position){ 
     int k=1; 
     NODE *p; 
     if(HEAD==NULL){ 
      printf("List Empty\n"); 
      return HEAD; 
     } 

     p=HEAD; 
     if(position==1){ 
      p=HEAD; 
      HEAD=HEAD->ptr; 
      free(p); 
      printf("Success!\n"); 
      return HEAD; 
     } 
     else{ 
      while(k<position-1){ 
       k++; 
       p=p->ptr; 
      } 

      if((p->ptr)==NULL) 
      { 
       printf("NO such position\n"); 
      } 
      else{ 
       free(p->ptr); 
       p->ptr=p->ptr->ptr; 
       printf("Success!\n"); 
      } 
     } 
    return HEAD; 
} 
+0

@pala做同樣的情況也會是不正確的。 – 2014-10-16 11:53:10

回答

1

不,這不行。這似乎是「工作」的唯一原因是因爲在你嘗試過的那些時候,內存分配器已經標記了你已經釋放的內存空間,但實際上並沒有覆蓋它或以其他方式觸及它,所以先前值仍然坐在那裏的內存地址。你不能指望這總是正確的。例如,如果該節點是特定頁面中最後分配的一塊內存,則沒有什麼可以阻止您執行free()將其從進程的虛擬內存表中刪除,從而導致您的下一次嘗試訪問它時出現分段違規。

使用一個臨時變量來代替:

NODE * tempnode = p->ptr->ptr; 
free(p->ptr); 
p->ptr = tempnode; 
+0

謝謝!這清除了我的懷疑! – 2014-10-16 11:56:19

0

你不能,也不應該。就像在刪除頭節點的第二個if語句中一樣使用中間變量。

+0

但是當我使用這個函數刪除一個節點並打印整個鏈表時,輸出結果是正確的。你能解釋爲什麼嗎? – 2014-10-16 11:39:24

+0

@ 2ndGenCore_i5這只是未定義的行爲。 – 2501 2014-10-16 11:44:10

+0

感謝您的洞察! – 2014-10-16 11:50:00