[bind] counterintuitive behavior with vector and auto_ptr

Hi there, I'm doing some job interview preparations. Always a good idea to go back to the basics and tinker around a bit. I came across a surprising behavior when using std::vector, std::auto_ptr, and boost::bind. Basically, I have a vector of auto_ptrs which is copied into a second vector, thus the first vector's auto_ptr loss their resource and point to nowhere. Basic stuff, as I said. Now, when I try to use an auto_ptr from the first vector using boost::bind everything still works. Meaning the code doesn't fail, although it should. I find that surprising. Why is boost::bind recreating the resource? Here is a my example code: #include <algorithm> #include <iostream> #include <vector> #include <boost/bind.hpp> using namespace std; struct A { A() { cout << "A::A();"; } ~A() { cout << "A::~A();"; } void foo() { cout << "A::foo();"; } }; auto_ptr< A > allocate_A() { return auto_ptr<A>( new A() ); } void call_foo( auto_ptr< A > p ) { p->foo(); } int main() { std::vector< auto_ptr< A > > v( 100 ); generate_n( v.begin(), 100, allocate_A ); for_each( v.begin(), v.end(), boost::bind( &A::foo, _1 )); std::vector< auto_ptr< A > > v2( 100 ); copy( v.begin(), v.end(), v2.begin() ); // auto_ptr in v should be empty now. // this fails //v[0]->foo(); // this fails //for_each( v.begin(), v.end(), call_foo ); // this doesn't fail for_each( v.begin(), v.end(), boost::bind( &A::foo, _1 )); return 0; } I'm using MSVC10 Express. Regards, Christian

AMDG Christian Henning wrote:
Hi there, I'm doing some job interview preparations. Always a good idea to go back to the basics and tinker around a bit. I came across a surprising behavior when using std::vector, std::auto_ptr, and boost::bind.
auto_ptr and vector don't mix. Use unique_ptr instead.
Basically, I have a vector of auto_ptrs which is copied into a second vector, thus the first vector's auto_ptr loss their resource and point to nowhere. Basic stuff, as I said. Now, when I try to use an auto_ptr from the first vector using boost::bind everything still works. Meaning the code doesn't fail, although it should. I find that surprising. Why is boost::bind recreating the resource?
It isn't. Boost.Bind passes the arguments by reference, so the auto_ptr is never copied. In Christ, Steven Watanabe

Hi there,
Basically, I have a vector of auto_ptrs which is copied into a second vector, thus the first vector's auto_ptr loss their resource and point to nowhere. Basic stuff, as I said. Now, when I try to use an auto_ptr from the first vector using boost::bind everything still works. Meaning the code doesn't fail, although it should. I find that surprising. Why is boost::bind recreating the resource?
It isn't. Boost.Bind passes the arguments by reference, so the auto_ptr is never copied.
All auto_ptrs have been copied a couple of lines before. See the std::copy call. After that my debugger tells me that all auto_ptrs are empty which makes sense. Still not clear to me what exactly happens when using bind. Christian

Hi, the reason why the for_each loop works, boost::bind unwraps the auto_ptr with get(), and get() does not trigger a debug break, but the operator -> does, so your other calls trigger a breakpoint (on release build this will be disabled and all test will pass). And the boost bind call of A::foo does not crash, because it does not touches 'this' of the object (the bind call uses the static address of A::foo and not the vtable of A). TJ. Am 12.06.2010, 08:41 Uhr, hast Du in gmane.comp.lib.boost.user geschrieben:
Hi there,
<---Schnitt--->
It isn't. Boost.Bind passes the arguments by reference, so the auto_ptr is never copied.
All auto_ptrs have been copied a couple of lines before. See the std::copy call. After that my debugger tells me that all auto_ptrs are empty which makes sense. Still not clear to me what exactly happens when using bind.
Christian

Thanks all. I can now see that the auto_ptr::get() doesn't throw but auto_ptr::operator->() does, although it's labeled as throw(). It only throws in debug mode, anyway. Thanks again, Christian On Fri, Jun 11, 2010 at 11:12 PM, <Tiemo.Jung@mni.fh-giessen.de> wrote:
Hi,
the reason why the for_each loop works, boost::bind unwraps the auto_ptr with get(), and get() does not trigger a debug break, but the operator -> does, so your other calls trigger a breakpoint (on release build this will be disabled and all test will pass). And the boost bind call of A::foo does not crash, because it does not touches 'this' of the object (the bind call uses the static address of A::foo and not the vtable of A).
TJ.
Am 12.06.2010, 08:41 Uhr, hast Du in gmane.comp.lib.boost.user geschrieben:
Hi there,
<---Schnitt--->
It isn't. Boost.Bind passes the arguments by reference, so the auto_ptr is never copied.
All auto_ptrs have been copied a couple of lines before. See the std::copy call. After that my debugger tells me that all auto_ptrs are empty which makes sense. Still not clear to me what exactly happens when using bind.
Christian
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Christian Henning wrote:
All auto_ptrs have been copied a couple of lines before. See the std::copy call. After that my debugger tells me that all auto_ptrs are empty which makes sense. Still not clear to me what exactly happens when using bind.
bind does the equivalent of p.get()->foo(). This doesn't call auto_ptr::operator->, whereas your two other examples do. So maybe VC10 has a get() != 0 assertion inside its op->.

On Fri, Jun 11, 2010 at 10:41 PM, Christian Henning <chhenning@gmail.com> wrote:
// this doesn't fail for_each( v.begin(), v.end(), boost::bind( &A::foo, _1 ));
Could it be that A::foo is called with null this, but since it doesn't use this it doesn't crash? Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
participants (5)
-
Christian Henning
-
Emil Dotchevski
-
Peter Dimov
-
Steven Watanabe
-
Tiemo.Jung@mni.fh-giessen.de