public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
To: Tobias Burnus <burnus@net-b.de>
Cc: rep.dot.nop@gmail.com, fortran@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH,FORTRAN] Fix memory leak in finalization wrappers
Date: Fri, 29 Oct 2021 01:58:57 +0200	[thread overview]
Message-ID: <20211029015857.14a80703@nbbrfq> (raw)
In-Reply-To: <20211027233943.082d66ed@nbbrfq>

On Wed, 27 Oct 2021 23:39:43 +0200
Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> wrote:

> Ping
> [hmz. it's been a while, I'll rebase and retest this one.
> Ok if it passes?]
Testing passed without any new regressions.
Ok for trunk?
thanks,
> 
> On Mon, 15 Oct 2018 10:23:06 +0200
> Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> wrote:
> 
> > If a finalization is not required we created a namespace containing
> > formal arguments for an internal interface definition but never used
> > any of these. So the whole sub_ns namespace was not wired up to the
> > program and consequently was never freed. The fix is to simply not
> > generate any finalization wrappers if we know that it will be unused.
> > Note that this reverts back to the original r190869
> > (8a96d64282ac534cb597f446f02ac5d0b13249cc) handling for this case
> > by reverting this specific part of r194075
> > (f1ee56b4be7cc3892e6ccc75d73033c129098e87) for PR fortran/37336.
> > 
> > Regtests cleanly, installed to the fortran-fe-stringpool branch, sent
> > here for reference and later inclusion.
> > I might plug a few more leaks in preparation of switching to hash-maps.
> > I fear that the leaks around interfaces are another candidate ;)
> > 
> > Should probably add a tag for the compile-time leak PR68800 shouldn't i.
> > 
> > valgrind summary for e.g.
> > gfortran.dg/abstract_type_3.f03 and gfortran.dg/abstract_type_4.f03
> > where ".orig" is pristine trunk and ".mine" contains this fix:
> > 
> > at3.orig.vg:LEAK SUMMARY:
> > at3.orig.vg-   definitely lost: 8,460 bytes in 11 blocks
> > at3.orig.vg-   indirectly lost: 13,288 bytes in 55 blocks
> > at3.orig.vg-     possibly lost: 0 bytes in 0 blocks
> > at3.orig.vg-   still reachable: 572,278 bytes in 2,142 blocks
> > at3.orig.vg-        suppressed: 0 bytes in 0 blocks
> > at3.orig.vg-
> > at3.orig.vg-Use --track-origins=yes to see where uninitialised values come from
> > at3.orig.vg-ERROR SUMMARY: 38 errors from 33 contexts (suppressed: 0 from 0)
> > --
> > at3.mine.vg:LEAK SUMMARY:
> > at3.mine.vg-   definitely lost: 344 bytes in 1 blocks
> > at3.mine.vg-   indirectly lost: 7,192 bytes in 18 blocks
> > at3.mine.vg-     possibly lost: 0 bytes in 0 blocks
> > at3.mine.vg-   still reachable: 572,278 bytes in 2,142 blocks
> > at3.mine.vg-        suppressed: 0 bytes in 0 blocks
> > at3.mine.vg-
> > at3.mine.vg-ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
> > at3.mine.vg-ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
> > at4.orig.vg:LEAK SUMMARY:
> > at4.orig.vg-   definitely lost: 13,751 bytes in 12 blocks
> > at4.orig.vg-   indirectly lost: 11,976 bytes in 60 blocks
> > at4.orig.vg-     possibly lost: 0 bytes in 0 blocks
> > at4.orig.vg-   still reachable: 572,278 bytes in 2,142 blocks
> > at4.orig.vg-        suppressed: 0 bytes in 0 blocks
> > at4.orig.vg-
> > at4.orig.vg-Use --track-origins=yes to see where uninitialised values come from
> > at4.orig.vg-ERROR SUMMARY: 18 errors from 16 contexts (suppressed: 0 from 0)
> > --
> > at4.mine.vg:LEAK SUMMARY:
> > at4.mine.vg-   definitely lost: 3,008 bytes in 3 blocks
> > at4.mine.vg-   indirectly lost: 4,056 bytes in 11 blocks
> > at4.mine.vg-     possibly lost: 0 bytes in 0 blocks
> > at4.mine.vg-   still reachable: 572,278 bytes in 2,142 blocks
> > at4.mine.vg-        suppressed: 0 bytes in 0 blocks
> > at4.mine.vg-
> > at4.mine.vg-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
> > at4.mine.vg-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
> > 
> > gcc/fortran/ChangeLog:
> > 
> > 2018-10-12  Bernhard Reutner-Fischer  <aldot@gcc.gnu.org>
> > 
> > 	* class.c (generate_finalization_wrapper): Do leak finalization
> > 	wrappers if they will not be used.
> > 	* expr.c (gfc_free_actual_arglist): Formatting fix.
> > 	* gfortran.h (gfc_free_symbol): Pass argument by reference.
> > 	(gfc_release_symbol): Likewise.
> > 	(gfc_free_namespace): Likewise.
> > 	* symbol.c (gfc_release_symbol): Adjust acordingly.
> > 	(free_components): Set procedure pointer components
> > 	of derived types to NULL after freeing.
> > 	(free_tb_tree): Likewise.
> > 	(gfc_free_symbol): Set sym to NULL after freeing.
> > 	(gfc_free_namespace): Set namespace to NULL after freeing.
> > ---
> >  gcc/fortran/class.c    | 25 +++++++++----------------
> >  gcc/fortran/expr.c     |  2 +-
> >  gcc/fortran/gfortran.h |  6 +++---
> >  gcc/fortran/symbol.c   | 19 ++++++++++---------
> >  4 files changed, 23 insertions(+), 29 deletions(-)
> > 
> > diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
> > index 69c95fc5dfa..e0bb381a55f 100644
> > --- a/gcc/fortran/class.c
> > +++ b/gcc/fortran/class.c
> > @@ -1533,7 +1533,6 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
> >    gfc_code *last_code, *block;
> >    const char *name;
> >    bool finalizable_comp = false;
> > -  bool expr_null_wrapper = false;
> >    gfc_expr *ancestor_wrapper = NULL, *rank;
> >    gfc_iterator *iter;
> >  
> > @@ -1561,13 +1560,17 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
> >      }
> >  
> >    /* No wrapper of the ancestor and no own FINAL subroutines and allocatable
> > -     components: Return a NULL() expression; we defer this a bit to have have
> > +     components: Return a NULL() expression; we defer this a bit to have
> >       an interface declaration.  */
> >    if ((!ancestor_wrapper || ancestor_wrapper->expr_type == EXPR_NULL)
> >        && !derived->attr.alloc_comp
> >        && (!derived->f2k_derived || !derived->f2k_derived->finalizers)
> >        && !has_finalizer_component (derived))
> > -    expr_null_wrapper = true;
> > +    {
> > +      vtab_final->initializer = gfc_get_null_expr (NULL);
> > +      gcc_assert (vtab_final->ts.interface == NULL);
> > +      return;
> > +    }
> >    else
> >      /* Check whether there are new allocatable components.  */
> >      for (comp = derived->components; comp; comp = comp->next)
> > @@ -1581,7 +1584,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
> >  
> >    /* If there is no new finalizer and no new allocatable, return with
> >       an expr to the ancestor's one.  */
> > -  if (!expr_null_wrapper && !finalizable_comp
> > +  if (!finalizable_comp
> >        && (!derived->f2k_derived || !derived->f2k_derived->finalizers))
> >      {
> >        gcc_assert (ancestor_wrapper && ancestor_wrapper->ref == NULL
> > @@ -1605,8 +1608,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
> >    /* Set up the namespace.  */
> >    sub_ns = gfc_get_namespace (ns, 0);
> >    sub_ns->sibling = ns->contained;
> > -  if (!expr_null_wrapper)
> > -    ns->contained = sub_ns;
> > +  ns->contained = sub_ns;
> >    sub_ns->resolved = 1;
> >  
> >    /* Set up the procedure symbol.  */
> > @@ -1622,7 +1624,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
> >    final->ts.kind = 4;
> >    final->attr.artificial = 1;
> >    final->attr.always_explicit = 1;
> > -  final->attr.if_source = expr_null_wrapper ? IFSRC_IFBODY : IFSRC_DECL;
> > +  final->attr.if_source = IFSRC_DECL;
> >    if (ns->proc_name->attr.flavor == FL_MODULE)
> >      final->module = ns->proc_name->name;
> >    gfc_set_sym_referenced (final);
> > @@ -1672,15 +1674,6 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
> >    final->formal->next->next->sym = fini_coarray;
> >    gfc_commit_symbol (fini_coarray);
> >  
> > -  /* Return with a NULL() expression but with an interface which has
> > -     the formal arguments.  */
> > -  if (expr_null_wrapper)
> > -    {
> > -      vtab_final->initializer = gfc_get_null_expr (NULL);
> > -      vtab_final->ts.interface = final;
> > -      return;
> > -    }
> > -
> >    /* Local variables.  */
> >  
> >    gfc_get_symbol (gfc_get_string ("%s", "idx"), sub_ns, &idx);
> > diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
> > index cc12e0a8402..3d744ec9641 100644
> > --- a/gcc/fortran/expr.c
> > +++ b/gcc/fortran/expr.c
> > @@ -533,7 +533,7 @@ gfc_free_actual_arglist (gfc_actual_arglist *a1)
> >      {
> >        a2 = a1->next;
> >        if (a1->expr)
> > -      gfc_free_expr (a1->expr);
> > +	gfc_free_expr (a1->expr);
> >        free (a1);
> >        a1 = a2;
> >      }
> > diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
> > index 4612835706b..3466c42132f 100644
> > --- a/gcc/fortran/gfortran.h
> > +++ b/gcc/fortran/gfortran.h
> > @@ -3032,8 +3032,8 @@ gfc_user_op *gfc_get_uop (const char *);
> >  gfc_user_op *gfc_find_uop (const char *, gfc_namespace *);
> >  const char *gfc_get_uop_from_name (const char*);
> >  const char *gfc_get_name_from_uop (const char*);
> > -void gfc_free_symbol (gfc_symbol *);
> > -void gfc_release_symbol (gfc_symbol *);
> > +void gfc_free_symbol (gfc_symbol *&);
> > +void gfc_release_symbol (gfc_symbol *&);
> >  gfc_symbol *gfc_new_symbol (const char *, gfc_namespace *);
> >  gfc_symtree* gfc_find_symtree_in_proc (const char *, gfc_namespace *);
> >  int gfc_find_symbol (const char *, gfc_namespace *, int, gfc_symbol **);
> > @@ -3058,7 +3058,7 @@ void gfc_commit_symbols (void);
> >  void gfc_commit_symbol (gfc_symbol *);
> >  gfc_charlen *gfc_new_charlen (gfc_namespace *, gfc_charlen *);
> >  void gfc_free_charlen (gfc_charlen *, gfc_charlen *);
> > -void gfc_free_namespace (gfc_namespace *);
> > +void gfc_free_namespace (gfc_namespace *&);
> >  
> >  void gfc_symbol_init_2 (void);
> >  void gfc_symbol_done_2 (void);
> > diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
> > index 09ad2bbf0cd..c99c106a0c0 100644
> > --- a/gcc/fortran/symbol.c
> > +++ b/gcc/fortran/symbol.c
> > @@ -2590,8 +2590,9 @@ free_components (gfc_component *p)
> >  	gfc_free_expr (p->kind_expr);
> >        if (p->param_list)
> >  	gfc_free_actual_arglist (p->param_list);
> > -      free (p->tb);
> >  
> > +      free (p->tb);
> > +      p->tb = NULL;
> >        free (p);
> >      }
> >  }
> > @@ -3070,7 +3071,7 @@ set_symbol_common_block (gfc_symbol *sym, gfc_common_head *common_block)
> >  /* Remove a gfc_symbol structure and everything it points to.  */
> >  
> >  void
> > -gfc_free_symbol (gfc_symbol *sym)
> > +gfc_free_symbol (gfc_symbol *&sym)
> >  {
> >  
> >    if (sym == NULL)
> > @@ -3078,8 +3079,6 @@ gfc_free_symbol (gfc_symbol *sym)
> >  
> >    gfc_free_array_spec (sym->as);
> >  
> > -  free_components (sym->components);
> > -
> >    gfc_free_expr (sym->value);
> >  
> >    gfc_free_namelist (sym->namelist);
> > @@ -3094,19 +3093,22 @@ gfc_free_symbol (gfc_symbol *sym)
> >  
> >    gfc_free_namespace (sym->f2k_derived);
> >  
> > +  free_components (sym->components);
> > +
> >    set_symbol_common_block (sym, NULL);
> >  
> >    if (sym->param_list)
> >      gfc_free_actual_arglist (sym->param_list);
> >  
> >    free (sym);
> > +  sym = NULL;
> >  }
> >  
> >  
> >  /* Decrease the reference counter and free memory when we reach zero.  */
> >  
> >  void
> > -gfc_release_symbol (gfc_symbol *sym)
> > +gfc_release_symbol (gfc_symbol *&sym)
> >  {
> >    if (sym == NULL)
> >      return;
> > @@ -3826,10 +3828,8 @@ free_tb_tree (gfc_symtree *t)
> >  
> >    free_tb_tree (t->left);
> >    free_tb_tree (t->right);
> > -
> > -  /* TODO: Free type-bound procedure structs themselves; probably needs some
> > -     sort of ref-counting mechanism.  */
> >    free (t->n.tb);
> > +  t->n.tb = NULL;
> >    free (t);
> >  }
> >  
> > @@ -4019,7 +4019,7 @@ free_entry_list (gfc_entry_list *el)
> >     taken care of when a specific name is freed.  */
> >  
> >  void
> > -gfc_free_namespace (gfc_namespace *ns)
> > +gfc_free_namespace (gfc_namespace *&ns)
> >  {
> >    gfc_namespace *p, *q;
> >    int i;
> > @@ -4057,6 +4057,7 @@ gfc_free_namespace (gfc_namespace *ns)
> >    gfc_free_data (ns->data);
> >    p = ns->contained;
> >    free (ns);
> > +  ns = NULL;
> >  
> >    /* Recursively free any contained namespaces.  */
> >    while (p != NULL)  
> 


  reply	other threads:[~2021-10-28 23:59 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-27 18:29 [Patch, Fortran] No-op Patch - a.k.a. FINAL wrapper update Tobias Burnus
2012-11-29 22:59 ` Janus Weil
2012-11-30  1:53   ` Tobias Burnus
2012-11-30 10:30     ` Janus Weil
2012-11-30 10:39       ` Janus Weil
2012-11-30 12:29       ` Tobias Burnus
2012-12-02 22:54         ` Janus Weil
2018-10-15  9:02           ` [PATCH,FORTRAN] Fix memory leak in finalization wrappers Bernhard Reutner-Fischer
2021-10-27 21:39             ` Bernhard Reutner-Fischer
2021-10-28 23:58               ` Bernhard Reutner-Fischer [this message]
2021-11-05 18:46                 ` Mikael Morin
2021-11-05 22:08                   ` Bernhard Reutner-Fischer
2021-11-06 12:04                     ` Mikael Morin
2021-11-06 23:56                       ` Bernhard Reutner-Fischer
2021-11-07 12:32                         ` Mikael Morin
2021-11-14 19:53                           ` Bernhard Reutner-Fischer
2021-11-06 10:30                   ` Mikael Morin

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=20211029015857.14a80703@nbbrfq \
    --to=rep.dot.nop@gmail.com \
    --cc=burnus@net-b.de \
    --cc=fortran@gcc.gnu.org \
    --cc=gcc-patches@gcc.gnu.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).