On Wed, Nov 02, 2022 at 11:01:40PM +0100, SZEDER Gábor wrote: > When processing a non-merge commit, the line-level log first asks the > tree-diff machinery whether any of the files in the given line ranges > were modified between the current commit and its parent, and if some > of them were, then it loads the contents of those files from both > commits to see whether their line ranges were modified and/or need to > be adjusted. Alas, it doesn't free() the diff queue holding the > results of that query and the contents of those files once its done. > This can add up to a substantial amount of leaked memory, especially > when the file in question is big and is frequently modified: a user > reported "Out of memory, malloc failed" errors with a 2MB text file > that was modified ~2800 times [1] (I estimate the leak would use up > almost 11GB memory in that case). > > Free that diff queue to plug this memory leak. However, instead of > simply open-coding the necessary three lines, add them as a helper > function to the diff API, because it will be useful elsewhere as well. Nicely explained. > --- > diff.c | 7 +++++++ > diffcore.h | 1 + > line-log.c | 1 + > 3 files changed, 9 insertions(+) And all looks reasonable here, good... > diff --git a/diff.c b/diff.c > index 35e46dd968..ef94175163 100644 > --- a/diff.c > +++ b/diff.c > @@ -5773,6 +5773,13 @@ void diff_free_filepair(struct diff_filepair *p) > free(p); > } > > +void diff_free_queue(struct diff_queue_struct *q) > +{ > + for (int i = 0; i < q->nr; i++) > + diff_free_filepair(q->queue[i]); > + free(q->queue); > +} Though I wonder, should diff_free_queue() be a noop when q is NULL? The caller in process_ranges_ordinary_commit() doesn't care, of course, since q is always non-NULL there. But if we're making it part of the diff API, we should probably err on the side of flexibility. Thanks, Taylor