[ASIO] destructor called multiple times in test code

I was messing around with the ASIO timer examples, the examples that test out the asynch-timers. I was trying to remove the Bind calls from those examples. I stumbled on the following behavior. I created a class function object and overloaded the () operator and would call t->async_wait(*this); in the constructor. And t->expires_at(t->expires_at() + boost::posix_time::seconds(1)); t->async_wait(*this); in the operator() overload function. Anyways to make a long story short the destructor that should have only been called once, gets called multiple times, but the constructor gets called once. To make things even funnier, the destructor has no affect when changing the value on member objects. ================================== Here is the code: class print{ int count; boost::asio::deadline_timer* t; int d_count; public: print (boost::asio::io_service& io, boost::asio::deadline_timer* timer) :count(0), t(timer), d_count(0){ std::cout<<"I'm in constructor: "<<count<<"\n"; t->async_wait(*this); }//end print ~print(){ std::cout << "Count=" << count << ","; std::cout << " D_count=" << ++d_count << "\n"; }//end ~print void operator ()(const boost::system::error_code& /*e*/){ if (count < 2){ std::cout << count << "\n"; ++(count); t->expires_at(t->expires_at() + boost::posix_time::seconds(1)); t->async_wait(*this); } }//end void operator() };//end class print int main(){ boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(1)); print p(io, &t); io.run(); return 0; } ============================== Here is the output: jose@jmart1:~/code/boost$ ./a.out I'm in constructor: 0 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 Count=0, D_count=1 0 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=0, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 Count=1, D_count=1 1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=1, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=2, D_count=1 Count=0, D_count=1 Any ideas what the heck is going on? Thanks a lot! jose "survival first, then happiness as we can manage it" ____________________________________________________________________________________ Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ ____________________________________________________________________________________ Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ

Jose Martinez wrote:
Anyways to make a long story short the destructor that should have only been called once, gets called multiple times, but the constructor gets called once. To make things even funnier, the destructor has no affect when changing the value on member objects.
================================== Here is the code: class print{ int count; boost::asio::deadline_timer* t; int d_count; public: print (boost::asio::io_service& io, boost::asio::deadline_timer* timer) :count(0), t(timer), d_count(0){ std::cout<<"I'm in constructor: "<<count<<"\n"; t->async_wait(*this); }//end print
~print(){ std::cout << "Count=" << count << ","; std::cout << " D_count=" << ++d_count << "\n"; }//end ~print
void operator ()(const boost::system::error_code& /*e*/){ if (count < 2){ std::cout << count << "\n"; ++(count); t->expires_at(t->expires_at() + boost::posix_time::seconds(1)); t->async_wait(*this); } }//end void operator() };//end class print
int main(){ boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(1)); print p(io, &t); io.run(); return 0; }
Hi Jose, If you add a copy constructor and operator= (although operator= doesn't seem to be used), it will make clear what is happening: p is being copied repeatedly. print(const print &p) : count(p.count), t(p.t), d_count(p.d_count){ std::cout<<"I'm in copy constructor: "<<count<<"\n"; } void operator=(const print &p) { count = p.count; t = p.t; d_count = p.d_count; std::cout<<"I'm in operator= : "<<count<<"\n"; } David

I've been confused by this too -- it comes up frequently. The trick is to instrument every constructor in your class -- even the copy constructor.

Hi! Jose Martinez schrieb:
I stumbled on the following behavior. I created a class function object and overloaded the () operator and would call
t->async_wait(*this);
Function objects are passed by value. This call will copy your object. The other posts already pointed that out. My recommendation is to follow common practise: make the operator() "const": void operator () (/*...*/) const {...} That way you cannot modify members. The "state" of the functor must be stored outside of the functor object. This way the state doesn't get copied. struct FunctorFoo { FunctorFoo(int& counter) : counter(&counter) {} int* const counter; void operator() () const { ++*counter; } }; (you could also use a "int& counter" member) Frank
participants (4)
-
David Walthall
-
Frank Birbacher
-
Jose Martinez
-
Nat Goodspeed