By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,187 Members | 1,594 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,187 IT Pros & Developers. It's quick & easy.

shared_ptr to incomplete type, undefined behavior?

P: n/a
From the standard 5.3.5/5:
"If the object being deleted has incomplete class type at the point of
deletion and the complete class has a non-trivial destructor or a
deallocation function, the behavior is undefined."

In the program below, what constitutes "point of deletion"? Presumably,
since delete is called somewhere within shared_ptr's template, the point
of deletion is the same place at which the template is instantiated.

Does the following program therefore exhibit undefined behavior, or am I
missing something? (Does this generalize to all cases in which a
shared_ptr is created from a forward reference?)
#include <iostream>
#include <boost/shared_ptr.hpp>

// Forward reference.
class A ;

// A has incomplete type here.
boost::shared_ptr<A> pa ;

class A
{
public:
A() { std::cout << "A()" << std::endl ; }
~A() { std::cout << "~A()" << std::endl ; }
} ;

int main()
{
pa.reset(new A) ;
}

--
Alan Johnson
May 13 '06 #1
Share this Question
Share on Google+
1 Reply


P: n/a
* Alan Johnson:
From the standard 5.3.5/5:
"If the object being deleted has incomplete class type at the point of
deletion and the complete class has a non-trivial destructor or a
deallocation function, the behavior is undefined."

In the program below, what constitutes "point of deletion"? Presumably,
since delete is called somewhere within shared_ptr's template, the point
of deletion is the same place at which the template is instantiated.
Does the following program therefore exhibit undefined behavior, or am I
missing something? (Does this generalize to all cases in which a
shared_ptr is created from a forward reference?)
#include <iostream>
#include <boost/shared_ptr.hpp>

// Forward reference.
class A ;

// A has incomplete type here.
boost::shared_ptr<A> pa ;

class A
{
public:
A() { std::cout << "A()" << std::endl ; }
~A() { std::cout << "~A()" << std::endl ; }
} ;

int main()
{
pa.reset(new A) ;
}


If you move the definition of class A to a separate file, plus a factory
function f that produces a raw pointer, and use f in 'main' instead of
direct use of 'new', then yes, in that case you would have UB --
except that the Boost code checks for this, so it won't compile:

// verify that types are complete for increased safety

template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}

However, as your code is it compiles, at least with MSVC 7.1, and so
(what an argument!) I think the instantiation of the template is at the
point of actual usage in 'main'.

Note that boost::shared_ptr provides a way to avoid UB even when you do
have an incomplete type, by passing a deleter function to the
constructor (that's why boost::shared_ptr is great for the PIMPL idiom).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
May 13 '06 #2

This discussion thread is closed

Replies have been disabled for this discussion.