From 033d4f38cd21b17ba878cce6c77501ef5b01f1d1 Mon Sep 17 00:00:00 2001 From: Orion Lawlor Date: Tue, 1 Oct 2024 23:27:23 -0800 Subject: [PATCH] Clarify what happens if target isn't found: find_indirect walks off the end of the list. --- README.md | 11 ++++++++--- src/list.c | 10 ++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fcda0e6..0901f34 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,10 @@ i.e. the address of the `next` element in the current `list_item`. When the pointer to the list item `*p` equals `target`, we exit the search loop and remove the item from the list. +(If `target` isn't in the list, and isn't NULL, then `find_indirect` will +dereference `NULL` and crash. If this case can happen, check if `*p == NULL` +inside the loop and handle this error appropriately.) + ## How does it work? @@ -254,6 +258,8 @@ void remove_elegant(list *l, list_item *target) } ``` + + ### Implementing `insert_before()` Using `find_indirect()`, it is straightforward to implement `insert_before()`: @@ -269,9 +275,8 @@ void insert_before(list *l, list_item *before, list_item *item) A particularly beautiful outcome is that the implementation has consistent semantics for the edge cases: if `before` points to the list head, the new item -will be inserted at the beginning of the list, if `before` is `NULL` or invalid -(i.e. the item does not exist in `l`), the new item will be appended at the -end. +will be inserted at the beginning of the list. If `before` is `NULL`, the +new item will be appended at the end of the list. ## Conclusion diff --git a/src/list.c b/src/list.c index 6dd41ad..6bca591 100644 --- a/src/list.c +++ b/src/list.c @@ -21,10 +21,11 @@ void remove_cs101(list *l, list_item *target) * This is a linear O(n) search. * * @param l A list of integers - * @param target The list item to find + * @param target The list item to find. Must exist in the list, or be NULL, + otherwise undefined behavior. * @return Pointer to the `next` pointer of the item that precedes * `target`, or `head`. Pointer to the last `next` field in the list - * if `target` is not in `l`. + * if `target` is NULL. */ static inline list_item **find_indirect(list *l, list_item *target) { @@ -51,8 +52,9 @@ void remove_elegant(list *l, list_item *target) * @param l A list of integers * @param before Pointer to item before which the new item should be inserted. * If `before` points to the list head, the new item will be - * inserted at the beginning; if `before` is NULL or invalid, - * the item will be appended at the the end of the list + * inserted at the beginning; if `before` is NULL, + * the item will be appended at the the end of the list; + * otherwise undefined behavior. * @param item The item to insert */ void insert_before(list *l, list_item *before, list_item *item)