This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/33504] New: redundant temporary object is created


looks like there is an ugly bug in g++ front-end.

the problem can be demonstrated by the existing testcase:
ext/pb_ds/regression/trie_data_map_rand.cc

if you apply the following diff:
.../libstdc++-v3/testsuite/util/regression/rand/assoc/detail/ $ svn di
Index: insert_fn_imps.hpp
===================================================================
--- insert_fn_imps.hpp  (revision 10694)
+++ insert_fn_imps.hpp  (working copy)
@@ -58,6 +58,7 @@
         value_type v = test_traits::generate_value(m_g, m_m);
         m_alloc.set_throw_prob(m_tp);
         const_key_reference r_k = test_traits::extract_key(v);
+        std::cerr << (int*)0xDEADbeaf << std::endl;
         typename cntnr::const_point_iterator found_it = m_p_c->find(r_k);
         const bool existed = (found_it != m_p_c->end());
         const std::pair<typename cntnr::point_iterator, bool> ins_ret =
m_p_c->insert(v);

trie_data_map_rand.cc will fail on sparc and x86 after random number
of 'deadbeaf' printouts compiled with -O0.
Looks like at least 4.2.x and most recent trunk are affected.

The above extra diff to the existing testcase just uncovers the problem.
Looks like the bug was there for long time and folks were lucky
not to hit it earlier.

Look into the -fdump-tree-gimple dump for the following function:
static typename Cntnr::const_key_reference
pb_ds::test::detail::regression_test_type_traits<Cntnr>::extract_key
(typename Cntnr::const_reference)
there you'll see that temporary object of 'struct pair' is created
and it's address passed into extract_key_imp() function.

The source code comes from here:
.../libstdc++-v3/testsuite/util/regression/trait/assoc/ $ svn di
Index: type_trait.hpp
===================================================================
--- type_trait.hpp      (revision 10694)
+++ type_trait.hpp      (working copy)
@@ -79,7 +79,7 @@

        static const_key_reference
         extract_key(const_reference r_val)
-       { return extract_key_imp(r_val); }
+       { return extract_key_imp(r_val); } // bug here

       private:
        typedef typename cntnr::allocator::template rebind<basic_type>::other


The mechanism of the bug is the following:
"r_k = test_traits::extract_key(v);" in insert_fn_imps.hpp eventually calls
"extract_key()" from type_trait.hpp above which creates a temp variable of
type "struct pair<basic_type,basic_type>" on stack and calls extract_key_imp()
with the address of that variable.
The returned address is actually the address of that stack temp variable,
so at the end 'r_k' points to already freed stack space.
Without '0xDEADbeaf' printout "m_p_c->find(r_k);" has a shorter
call chain than "extract_key()" and "find(r_k)" doesn't overwrite that
stack space, 'r_k' value is valid and everything works.
'deadbeaf' printout reuses that stack space and when it comes to
"m_p_c->find(r_k)", 'r_k' points to trash and 'find' sooner or later
coredumps.

Unfortunately I wasn't able to create a shorter testcase out of
trie_data_map_rand.cc
Various combination of
detail::regression_test_type_traits<s>::extract_key (ref);
with different 's' and 'ref' didn't expose the creation of such
extra temp variable.

As the summary 'extract_key' is supposed to look like:

static typename Cntnr::const_key_reference
pb_ds::test::detail::regression_test_type_traits<Cntnr>::extract_key
(typename Cntnr::const_reference) [with Cntnr = ...] (r_val)
{
  const struct basic_type & D.82957;
  const struct basic_type & D.82958;

  D.82958 = extract_key_imp (r_val);
  D.82957 = D.82958;
  return D.82957;
}

incorrect 'extract_key' may look like:

static typename Cntnr::const_key_reference
pb_ds::test::detail::regression_test_type_traits<Cntnr>::extract_key
(typename Cntnr::const_reference) [with Cntnr = ...] (r_val)
{
  const struct basic_type & D.107098;
  const struct pair D.107097;
  struct pair * D.107099;
  const struct basic_type & D.107100;

  __comp_ctor  (&D.107097, r_val);
  try
    {
      D.107100 = extract_key_imp (&D.107097);
      D.107098 = D.107100;
      return D.107098;
    }
  finally
    {
      D.107099 = (struct pair *) &D.107097;
      __comp_dtor  (D.107099);
    }
}


-- 
           Summary: redundant temporary object is created
           Product: gcc
           Version: 4.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: alexey dot starovoytov at sun dot com
 GCC build triplet: sll
  GCC host triplet: all
GCC target triplet: all


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33504


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]