From 119ab07a468964bd59e51ba8f4cdce409a2ed504 Mon Sep 17 00:00:00 2001 From: a bellenir Date: Fri, 1 Aug 2014 02:39:36 +0000 Subject: [PATCH] fix memleak in list_delete_node --- source/list/list.c | 1 + tests/test_list.c | 168 ++++++++++++++++++++++++++------------------- 2 files changed, 98 insertions(+), 71 deletions(-) diff --git a/source/list/list.c b/source/list/list.c index 27e13d1..5f06f20 100644 --- a/source/list/list.c +++ b/source/list/list.c @@ -234,6 +234,7 @@ void list_delete_node(list_t* list, list_node_t* node) if(list->head == node) list->head = node->next; if(list->tail == node) list->tail = prev; node->next = NULL; + mem_release(node); } /* else node not found, do nothing. */ } } diff --git a/tests/test_list.c b/tests/test_list.c index 382fe0f..5965223 100644 --- a/tests/test_list.c +++ b/tests/test_list.c @@ -633,106 +633,132 @@ TEST_SUITE(List) { //------------------------------------------------------------------------- TEST(Verify_delete_node_does_nothing_if_list_is_empty) { - list_t list = { NULL, NULL }; + list_t* list = list_new(); list_node_t bogus = { NULL, NULL }; - list_delete_node(&list, NULL); - CHECK( NULL == list.head); - CHECK( NULL == list.tail); - list_delete_node(&list, &bogus); - CHECK( NULL == list.head); - CHECK( NULL == list.tail); + list_delete_node(list, NULL); + CHECK( NULL == list->head); + CHECK( NULL == list->tail); + list_delete_node(list, &bogus); + CHECK( NULL == list->head); + CHECK( NULL == list->tail); + mem_release(list); } TEST(Verify_delete_node_does_nothing_if_given_node_not_in_list) { - list_node_t node3 = { NULL, NULL }; - list_node_t node2 = { NULL, &node3 }; - list_node_t node1 = { NULL, &node2 }; - list_t list = { &node1, &node3 }; - list_node_t bogus = { NULL, &node2 }; - list_delete_node(&list, &bogus); - CHECK( &node2 == bogus.next ); - CHECK( &node1 == list.head ); - CHECK( &node2 == node1.next ); - CHECK( &node3 == node2.next ); - CHECK( NULL == node3.next ); - CHECK( &node3 == list.tail ); + list_t* list = list_new(); + list_node_t* node3 = list_insert_after(list, NULL, mem_box(0x4321)); + list_node_t* node2 = list_insert_after(list, NULL, mem_box(0x4242)); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0x1234)); + list_node_t bogus = { NULL, node2 }; + list_delete_node(list, &bogus); + CHECK( node2 == bogus.next ); + CHECK( node1 == list->head ); + CHECK( node2 == node1->next ); + CHECK( node3 == node2->next ); + CHECK( NULL == node3->next ); + CHECK( node3 == list->tail ); + mem_release(list); } TEST(Verify_delete_node_deletes_the_head_node_of_a_list_of_length_1) { - list_node_t node1 = { NULL, NULL }; - list_t list = { &node1, &node1 }; - list_delete_node(&list, &node1); - CHECK( NULL == node1.next ); - CHECK( NULL == list.head ); - CHECK( NULL == list.tail ); + list_t* list = list_new(); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0x1337)); + mem_retain(node1); + list_delete_node(list, node1); + CHECK( 1 == mem_num_references(node1) ); + CHECK( NULL == node1->next ); + CHECK( NULL == list->head ); + CHECK( NULL == list->tail ); + mem_release(list); + mem_release(node1); } TEST(Verify_delete_node_deletes_the_first_element_of_a_list_of_length_2) { - list_node_t node2 = { NULL, NULL }; - list_node_t node1 = { NULL, &node2 }; - list_t list = { &node1, &node2 }; - list_delete_node(&list, &node1); - CHECK( NULL == node1.next ); - CHECK( &node2 == list.head ); - CHECK( NULL == node2.next ); - CHECK( &node2 == list.tail ); + list_t* list = list_new(); + list_node_t* node2 = list_insert_after(list, NULL, mem_box(0xDEAD)); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0xBEEF)); + mem_retain(node1); + list_delete_node(list, node1); + CHECK( 1 == mem_num_references(node1) ); + CHECK( NULL == node1->next ); + CHECK( node2 == list->head ); + CHECK( NULL == node2->next ); + CHECK( node2 == list->tail ); + mem_release(list); + mem_release(node1); } TEST(Verify_delete_node_deletes_the_second_element_of_a_list_of_length_2) { - list_node_t node2 = { NULL, NULL }; - list_node_t node1 = { NULL, &node2 }; - list_t list = { &node1, &node2 }; - list_delete_node(&list, &node2); - CHECK( NULL == node2.next ); - CHECK( &node1 == list.head ); - CHECK( NULL == node1.next ); - CHECK( &node1 == list.tail ); + list_t* list = list_new(); + list_node_t* node2 = list_insert_after(list, NULL, mem_box(0xBEAD)); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0xDAD0)); + mem_retain(node2); + list_delete_node(list, node2); + CHECK( 1 == mem_num_references(node2) ); + CHECK( NULL == node2->next ); + CHECK( node1 == list->head ); + CHECK( NULL == node1->next ); + CHECK( node1 == list->tail ); + mem_release(list); + mem_release(node2); } TEST(Verify_delete_node_deletes_the_first_element_of_a_list_of_length_3) { - list_node_t node3 = { NULL, NULL }; - list_node_t node2 = { NULL, &node3 }; - list_node_t node1 = { NULL, &node2 }; - list_t list = { &node1, &node3 }; - list_delete_node(&list, &node1); - CHECK( NULL == node1.next ); - CHECK( &node2 == list.head ); - CHECK( &node3 == node2.next ); - CHECK( NULL == node3.next ); - CHECK( &node3 == list.tail ); + list_t* list = list_new(); + list_node_t* node3 = list_insert_after(list, NULL, mem_box(0x1337)); + list_node_t* node2 = list_insert_after(list, NULL, mem_box(0x1234)); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0x4321)); + mem_retain(node1); + list_delete_node(list, node1); + CHECK( 1 == mem_num_references(node1) ); + CHECK( NULL == node1->next ); + CHECK( node2 == list->head ); + CHECK( node3 == node2->next ); + CHECK( NULL == node3->next ); + CHECK( node3 == list->tail ); + mem_release(list); + mem_release(node1); } TEST(Verify_delete_node_deletes_the_second_element_of_a_list_of_length_3) { - list_node_t node3 = { NULL, NULL }; - list_node_t node2 = { NULL, &node3 }; - list_node_t node1 = { NULL, &node2 }; - list_t list = { &node1, &node3 }; - list_delete_node(&list, &node2); - CHECK( NULL == node2.next ); - CHECK( &node1 == list.head ); - CHECK( &node3 == node1.next ); - CHECK( NULL == node3.next ); - CHECK( &node3 == list.tail ); + list_t* list = list_new(); + list_node_t* node3 = list_insert_after(list, NULL, mem_box(0x1337)); + list_node_t* node2 = list_insert_after(list, NULL, mem_box(0x4242)); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0xBEEF)); + mem_retain(node2); + list_delete_node(list, node2); + CHECK( 1 == mem_num_references(node2) ); + CHECK( NULL == node2->next ); + CHECK( node1 == list->head ); + CHECK( node3 == node1->next ); + CHECK( NULL == node3->next ); + CHECK( node3 == list->tail ); + mem_release(list); + mem_release(node2); } TEST(Verify_delete_node_deletes_the_third_element_of_a_list_of_length_3) { - list_node_t node3 = { NULL, NULL }; - list_node_t node2 = { NULL, &node3 }; - list_node_t node1 = { NULL, &node2 }; - list_t list = { &node1, &node3 }; - list_delete_node(&list, &node3); - CHECK( NULL == node3.next ); - CHECK( &node1 == list.head ); - CHECK( &node2 == node1.next ); - CHECK( NULL == node2.next ); - CHECK( &node2 == list.tail ); + list_t* list = list_new(); + list_node_t* node3 = list_insert_after(list, NULL, mem_box(0x4321)); + list_node_t* node2 = list_insert_after(list, NULL, mem_box(0x4242)); + list_node_t* node1 = list_insert_after(list, NULL, mem_box(0x1337)); + mem_retain(node3); + list_delete_node(list, node3); + CHECK( 1 == mem_num_references(node3) ); + CHECK( NULL == node3->next ); + CHECK( node1 == list->head ); + CHECK( node2 == node1->next ); + CHECK( NULL == node2->next ); + CHECK( node2 == list->tail ); + mem_release(list); + mem_release(node3); } //------------------------------------------------------------------------- -- 2.52.0