2016-06-21 26 views
0

這是一個小測試,以幫助演示和檢查valgrind的memcheck的輸出。有人可以幫我弄清楚如何從列表中間刪除並釋放一個節點?如果我註釋掉remove節點中的免費(cur-)和free(cur-> lock),那麼memcheck告訴我我有內存泄漏,但是如果我將它們保留在那裏,那麼我會在頂部進行無效讀取循環。有沒有辦法解決這個難題?如何在沒有valgrind錯誤的情況下釋放列表中間的已刪除節點?

TEST(UtilityGeneralUnittest, valgrindTests) 
{ 
    //declare a node type 
    typedef struct node{ 
     int size; 
     int value; 
     struct node *next; 
     pthread_mutex_t *lock; 
    }node_t; 

    //make the head 
    node_t *head; 
    head = (node_t*)malloc(1 * sizeof(node_t)); 
    head->size = 0; 
    head->next = NULL; 
    head->lock = (pthread_mutex_t*)malloc(1 * sizeof(pthread_mutex_t)); 
    pthread_mutex_init(head->lock, NULL); 

    //create array for storing values 
    int array[10]; 


    //build a list with random numbers 
    for (int i = 0; i < 10; i++) 
    { 
     node_t *newNode; 
     newNode = (node_t*)malloc(1 * sizeof(node_t)); 
     newNode->value = rand() % 100 + 1; 
     newNode->next = NULL; 
     newNode->lock = (pthread_mutex_t*) malloc(1 * sizeof(pthread_mutex_t)); 
     pthread_mutex_init(newNode->lock, NULL); 
     array[i] = newNode->value; 
     if (head->next == NULL) 
     { 
      head->next = newNode; 
      head->size++; 
     } 
     else 
     { 
      node_t *tmp = head->next; 
      head->next = newNode; 
      newNode->next = tmp; 
      head->size++; 
     } 
    } 
    // assert the list added nodes 
    ASSERT_EQ(10, head->size); 

    //sanity check; print the list 
    node_t *printer = head; 
    while(printer->next != NULL) 
    { 
     printer = printer->next; 
     std::cout << "value: "; 
     std::cout << printer->value << ", "; 
    } 
    std::cout << "\n"; 
    // the meat and potatoes: deleting with locks. 
    int removeMe = array[rand() % 10]; 
    bool verifyDel = true; 
    int checkVal = removeMe; 
    node_t *prev; 
    node_t *cur; 

    prev = head; 
    pthread_mutex_lock(prev->lock); 
    while((cur = prev->next) != NULL) //******** this is the problem 
    { 
     pthread_mutex_lock(cur->lock); 
     if(cur->value == removeMe) 
     { 
      prev->next = cur->next; 
      pthread_mutex_unlock(cur->lock); 
      pthread_mutex_unlock(prev->lock); 
      cur->next = NULL; 
      head->size--; 
      free(cur->lock); ///******** this is the problem 
      free(cur); ///****** this is the problem 
     } 
     pthread_mutex_unlock(prev->lock); 
     prev = cur; 
    } 
    //pthread_mutex_unlock(prev->lock); 


    //verify node has been removed 
    printer = head; 
    while(printer->next != NULL) 
    { 
     printer = printer->next; 
     if(printer->value == checkVal) 
     { 
      verifyDel = false; 
     } 
     std::cout << "value: "; 
     std::cout << printer->value << ", "; 
    } 
    std::cout << "\n"; 
    ASSERT_TRUE(verifyDel); 

    //clean up: delete the list 
    while((printer = head) != NULL) 
    { 
     head = head->next; 
     free(printer->lock); 
     free(printer); 
     std::cout << "free!!!" << std::endl; 
    } 


} 
+0

你似乎比你鎖定到解鎖互斥次... –

+0

@TobySpeight對此深感抱歉,是的,這是一個gTest測試案例。我會想象你可以將函數的內容複製到main()中,然後編譯並運行。使用malloc()是我作爲一名C程序員的日子辛苦:)。我會試一試你的建議,並對這項任務進行測試。讓你知道! –

+0

@TobySpeight你是對的,這是分配。我沒有在任務周圍添加測試用例,而是在繼續查看我的答案。 –

回答

1

看你的循環(簡體):

while ((cur = prev->next) != NULL) //* problem 
{ 
    if (cur->value == removeMe) 
    { 
     prev->next = cur->next; 
     cur->next = NULL; 
     free(cur);    //* problem 
    } 
    prev = cur; 
} 

問題是與分配prev = cur,但只有當if塊進行評估。那已經釋放了cur,所以下一次循環時,cur=prev->next引用已刪除的存儲。

您可以修復,可通過將else分配prev只有當cur沒有被刪除:

while ((cur = prev->next)) { 
    if (cur->value == removeMe) { 
     prev->next = cur->next; 
     cur->next = NULL; 
     free(cur); 
    } else { 
     prev = cur; 
    } 
} 
相關問題