Spurious destructor call, or ill-formed code?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I ran into this while porting some code from Linux to FreeBSD, and I isolated this to a small example. The example uses a class that dumps a diagnostic in its constructor and destructor, and juggles a couple of instances of the class, using a couple of lambdas.

"g++47 (FreeBSD Ports Collection) 4.7.0 20111203 (experimental)" invokes the destructor of two instances of this class twice. Sample output (highlighting what I've now wasted a week on):

$ /tmp/t
Constructed 0x7fffffffdb00: 24
other: 24: 0x7fffffffdb00
Copied 0x7fffffffdb00 to 0x7fffffffdb20
Constructed 0x7fffffffdb30: 42
orig: 42: 0x7fffffffdb30
Copied 0x7fffffffdb30 to 0x7fffffffda90
cpy: 42: 0x7fffffffda90
Copied 0x7fffffffdb20 to 0x7fffffffda80
Copied 0x7fffffffda90 to 0x7fffffffdac0
Copied 0x7fffffffda80 to 0x7fffffffdac4
lambda: 42: 0x7fffffffdac0
other_lambda: 24: 0x7fffffffdac4
Destroyed 0x7fffffffdac0       ******
Destroyed 0x7fffffffdac4       ******
Destroyed 0x7fffffffdac4       ******
Destroyed 0x7fffffffdac0       ******
Destroyed 0x7fffffffda80
Destroyed 0x7fffffffda90
Destroyed 0x7fffffffdb30
Destroyed 0x7fffffffdb20
Destroyed 0x7fffffffdb00

With "g++ (GCC) 4.7.0 20120507 (Red Hat 4.7.0-5)" the extra destructor calls do not occur. The output is the same, except for two of the destructor calls (ignoring the differences in the pointer values).

In both cases, I'm using only -std=c++0x to compile the following. As far as I can tell, I'm capturing everything by value, and I can't see what's ill- formed here:

#include <iostream>
#include <string>
#include <type_traits>

class sw {

public:
   int s;

   sw(const int &sa) : s(sa)
   {
       std::cout << "Constructed " << this << ": " << s << std::endl;
   }

   ~sw()
   {
       std::cout << "Destroyed " << this << std::endl;
   }

   sw(const sw &o) : s(o.s)
   {
       std::cout << "Copied " << &o << " to " << this << std::endl;
   }

   sw &operator=(const sw &o)
   {
       s=o.s;
       std::cout << "Assigned " << &o << " to " << this << std::endl;
       return *this;
   }

   void identify(const std::string &str) const
   {
       std::cout << str << ": " << s << ": " << this << std::endl;
   }
};

template<typename lambda2>
void foo(sw &&orig, lambda2 &&lambda)
{
   orig.identify("orig");

   sw cpy(orig);

   cpy.identify("cpy");

   lambda2 lambda_cpy(std::move(lambda));

   [cpy, lambda_cpy]
   {
       cpy.identify("lambda");

       lambda_cpy();
   }();
}

int main(int argc, char **argv)
{
   sw other(24);

   other.identify("other");

   foo(sw(42),
       [other]
       {
           other.identify("other_lambda");
       });
   return (0);
}

Attachment: pgpj8HZhsPNXt.pgp
Description: PGP signature


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux