git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/3] dir: make clear_directory() free all relevant memory

From
Jeff King <peff@peff.net>
Date
Aug 16, 2020, 08:54 UTC
Message-ID
<20200816085406.GB1221900@coredump.intra.peff.net>
In-Reply-To
<068e097e22fa42b79e70b0346cc7460f1a3cbcff.1597561152.git.gitgitgadget@gmail.com>
On Sun, Aug 16, 2020 at 06:59:10AM +0000, Elijah Newren via GitGitGadget wrote:
Show 15 quoted lines
> From: Elijah Newren <newren@gmail.com>
> 
> The calling convention for the dir API is supposed to end with a call to
> clear_directory() to free up no longer needed memory.  However,
> clear_directory() didn't free dir->entries or dir->ignored.  I believe
> this was oversight, but a number of callers noticed memory leaks and
> started free'ing these, but often somewhat haphazardly (sometimes
> freeing the entries in the arrays, and sometimes only free'ing the
> arrays themselves).  This suggests the callers weren't trying to make
> sure any possible memory used might be free'd, but just the memory they
> noticed their usecase definitely had allocated.  This also caused the
> extra memory deallocations to be duplicated in many places.
> 
> Fix this mess by moving all the duplicated free'ing logic into
> clear_directory().

Makes sense. I don't know the dir.c code very well, so my worry would be that some caller really wanted the other fields left untouched. But looking over the callers, it seems they're all clearing it before the struct goes out of scope. It's possible that they could have created other pointer references, but it seems unlikely (and I'd argue they should stop doing that and make their own copies of the data). E.g., wt_status_collect_untracked() sticks names into a string_list, but it sets strdup_strings to make its own copy, so it's good.

Show 14 quoted lines
> @@ -3034,6 +3031,13 @@ void clear_directory(struct dir_struct *dir)
>  		free(group->pl);
>  	}
>  
> +	for (i = 0; i < dir->ignored_nr; i++)
> +		free(dir->ignored[i]);
> +	for (i = 0; i < dir->nr; i++)
> +		free(dir->entries[i]);
> +	free(dir->ignored);
> +	free(dir->entries);
> +
>  	stk = dir->exclude_stack;
>  	while (stk) {
>  		struct exclude_stack *prev = stk->prev;

In most of our "clear" functions, the struct is ready for use again (i.e., fields are set back to the initialized state). I don't think any caller cares at this point, but it may be worth doing while we are here as a least-surprise thing. That would mean setting these pointers to NULL, and probably a few others that you aren't touching here.

Perhaps even easier would be to add a dir_init() call at the end after your next patch adds that function.

-Peff
Previous: Elijah Newren via GitGitGadgetNext: Elijah Newren
Message 10 of 15 in “Clean up some memory leaks in and around dir.c”
  1. 0/3 Clean up some memory leaks in and around dir.cElijah Newren via GitGitGadget, Aug 16, 2020
  2. 1/3 dir: fix leak of parent_hashmap and recursive_hashmapElijah Newren via GitGitGadget, Aug 16, 2020
  3. Jeff KingAug 16, 2020
  4. Elijah NewrenAug 17, 2020
  5. 3/3 dir: fix problematic API to avoid memory leaksElijah Newren via GitGitGadget, Aug 16, 2020
  6. Jeff KingAug 16, 2020
  7. Elijah NewrenAug 17, 2020
  8. Jeff KingAug 17, 2020
  9. 2/3 dir: make clear_directory() free all relevant memoryElijah Newren via GitGitGadget, Aug 16, 2020
  10. Jeff KingAug 16, 2020
  11. Elijah NewrenAug 17, 2020
  12. 0/2 Clean up some memory leaks in and around dir.cElijah Newren via GitGitGadget, Aug 18, 2020
  13. 1/2 dir: make clear_directory() free all relevant memoryElijah Newren via GitGitGadget, Aug 18, 2020
  14. 2/2 dir: fix problematic API to avoid memory leaksElijah Newren via GitGitGadget, Aug 18, 2020
  15. Jeff KingAug 19, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.