Subject: Re: [[RFC memory leak, v.2]] Minor memory leak fix

From: René Scharfe <[email-masked]>
Date: Tue, 11 Mar 2014 20:40:07 +0100

Am 11.03.2014 13:36, schrieb Fredrik Gustafsson:
> Strbuf needs to be released even if it's locally declared.
>
> Signed-off-by: Fredrik Gustafsson <[email-masked]>
> ---
>   archive.c | 16 ++++++++++------
>   1 file changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/archive.c b/archive.c
> index 346f3b2..dfc557d 100644
> --- a/archive.c
> +++ b/archive.c
> @@ -113,6 +113,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
>   	struct git_attr_check check[2];
>   	const char *path_without_prefix;
>   	int err;
> +	int to_ret = 0;
>
>   	args->convert = 0;
>   	strbuf_reset(&path);
> @@ -127,22 +128,25 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
>   	setup_archive_check(check);
>   	if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
>   		if (ATTR_TRUE(check[0].value))
> -			return 0;
> +			goto cleanup;
>   		args->convert = ATTR_TRUE(check[1].value);
>   	}
>
>   	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
>   		if (args->verbose)
>   			fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
> -		err = write_entry(args, sha1, path.buf, path.len, mode);
> -		if (err)
> -			return err;
> -		return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
> +		to_ret = write_entry(args, sha1, path.buf, path.len, mode);
> +		if (!to_ret)
> +			to_ret = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
> +		goto cleanup;

Why add to_ret when you can use the existing variable err directly?  Or 
at least remove it when it's not used anymore.

>   	}
>
>   	if (args->verbose)
>   		fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
> -	return write_entry(args, sha1, path.buf, path.len, mode);
> +	to_ret = write_entry(args, sha1, path.buf, path.len, mode);
> +cleanup:
> +	strbuf_release(&path);
> +	return to_ret;

If you free the memory of the strbuf at the end of the function then 
there is no point in keeping it static anymore.  Growing it to PATH_MAX 
also doesn't make as much sense as before then.

The patch makes git archive allocate and free the path strbuf once per 
archive entry, while before it allocated only once per run and left 
freeing to the OS.  What's the performance impact of this change?

>   }
>
>   int write_archive_entries(struct archiver_args *args,
>