All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Alexander Kuleshov <kuleshovmail@gmail.com>
Cc: "git\@vger.kernel.org" <git@vger.kernel.org>,
	Jeff King <peff@peff.net>,
	Eric Sunshine <sunshine@sunshineco.com>
Subject: Re: Re*: [PATCH] change contract between system_path and it's callers
Date: Tue, 25 Nov 2014 09:55:39 -0800	[thread overview]
Message-ID: <xmqqbnnvtbac.fsf@gitster.dls.corp.google.com> (raw)
In-Reply-To: <CANCZXo4C_6Zfob9VnxjGxPbsRnUioVqC10z3Hhv09_xtrx-Pog@mail.gmail.com> (Alexander Kuleshov's message of "Tue, 25 Nov 2014 13:04:46 +0600")

Alexander Kuleshov <kuleshovmail@gmail.com> writes:

> But if we still static const char* for git_etc_gitattributes and will
> not free it in bootstrap_attr_stack there will no memory leak, just
> tested it, so i'll remove free for it.

Leak or no leak, freeing there is wrong.  It will free the piece of
memory the next caller will obtain from the git_etc_gitattributes()
function.  In other words, the return value from that function is
owned by git_etc_gitattributes(), not by the caller.

As to "leak", in the strictest sense of the word, i.e. "do we
allocate on the heap and exit without freeing?", it _is_ leaking,
and your above "just tested it" probably means "the tool I used did
not find/report it".  But as I said, it is not something worth
bothering about [*1*].

Think of it this way.

The git_etc_gitattributes() function goes like this with your patch
(and there is no fundamental difference in the original version,
which uses "const char *" where appropriate):

         static char *git_etc_gitattributes(void)
         {
                static char *system_wide;
                if (!system_wide)
                        system_wide = system_path(ETC_GITATTRIBUTES);
                return system_wide;
         }

If you knew that the pathname for /etc/gitattributes substitute will
never be longer than 256 bytes, you may have coded the above like so
instead:

        static char system_wide[256];
        static char *git_etc_gitattributes(void)
        {
                if (!system_wide[0]) {
                        char *ret = system_path(ETC_GITATTRIBUTES);
                        if (strncpy(system_wide, ret, 256) >= 256)
                                die("ETC_GITATTRIBUTES too long ");
                }       
                return system_wide;
        }

Even though we used the memory occupied by system_wide[] and did not
clean up before exit(), nobody would complain about leaking.

The existing code is the moral equivalent of the "up to 256 bytes"
illustration, but for a string whose size is not known at compile
time.  It is using and keeping the memory until program exit.
Nobody should complain about leaking.

That is, unless (1) the held memory is expected to be very large and
(2) you can prove that after the point you decide to insert free(),
nobody will ever need that information again.


[Footnote]

*1* The leaks we care about are of this form:

    void silly_leaker(void)
    {
        printf("%s\n", system_path(ETC_GITATTRIBUTES));
    }

    where each invocation allocates memory, uses it and then loses
    the reference to it without doing anything to clean-up.  You can
    call such a function unbounded number of times and waste
    unbounded amount of memory.

    The implementation of git_etc_gitattributes() is not of that
    kind.  An invocation of it allocates, uses and keeps.  The
    second and subsequent invocation does not allocate.  When you
    call it unbounded number of times, it does not waste unbounded
    amount of memory.  It just keeps what it needs to answer the
    next caller with.

    The pattern needs to be made thread-safe, but that is a separate
    topic.

  reply	other threads:[~2014-11-25 17:55 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-23 13:56 GIT: [PATCH] exec_cmd: system_path memory leak fix 0xAX
2014-11-23 13:56 ` 0xAX
2014-11-23 14:01   ` 0xAX
2014-11-23 18:51   ` Junio C Hamano
2014-11-23 19:06     ` Alex Kuleshov
2014-11-23 19:19     ` Alex Kuleshov
2014-11-23 19:42       ` Jeff King
2014-11-23 20:07       ` Eric Sunshine
2014-11-23 21:58       ` Junio C Hamano
2014-11-24  7:02         ` Alex Kuleshov
2014-11-24  7:37           ` Junio C Hamano
2014-11-24  8:12             ` Alex Kuleshov
2014-11-24 13:11             ` Alexander Kuleshov
2014-11-24 14:00             ` Alex Kuleshov
2014-11-24 14:07               ` [PATCH] change contract between system_path and it's callers 0xAX
2014-11-24 19:33                 ` Re*: " Junio C Hamano
2014-11-24 19:53                   ` Alex Kuleshov
2014-11-24 20:20                     ` Junio C Hamano
2014-11-24 20:50                     ` Junio C Hamano
2014-11-25  6:45                       ` Alexander Kuleshov
2014-11-25  7:04                         ` Alexander Kuleshov
2014-11-25 17:55                           ` Junio C Hamano [this message]
2014-11-25 18:03                             ` Alexander Kuleshov
2014-11-25 18:24                               ` [PATCH 1/1] " Alexander Kuleshov
2014-11-25 21:13                                 ` Junio C Hamano
2014-11-26  3:53                                   ` Alexander Kuleshov
2014-11-26  9:42                                     ` Alexander Kuleshov
2014-11-26 14:00                                       ` Alexander Kuleshov
2014-11-26 17:53                                     ` Junio C Hamano
2014-11-28 13:09                                     ` Philip Oakley
2014-11-25 20:20                               ` Re*: [PATCH] " Junio C Hamano
2014-11-25 17:59                           ` Alexander Kuleshov
2014-11-23 18:28 ` GIT: [PATCH] exec_cmd: system_path memory leak fix Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqbnnvtbac.fsf@gitster.dls.corp.google.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=kuleshovmail@gmail.com \
    --cc=peff@peff.net \
    --cc=sunshine@sunshineco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.