473,395 Members | 1,941 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Deleting a pointer to an incomplete class

Does the following have undefined behavior?

struct X;

struct Y {

X * x_ptr;

Y ( void )
: x_ptr ( 0 )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X {};

int main ( void ) {
Y y;
}
Note that struct X is defined after struct Y is defined but before a
variable of type Y is declared. I feel that it should depend on when/where
the destructor ~Y is instantiated; but the language in the standard is
frightening and I am not sure that, left to my own devices, I would arrive
at the commonly accepted interpretation.

I just note that Comeau gives a warning and g++ accepts the code without
complaint.
Best

Kai-Uwe Bux
Jul 11 '07 #1
2 6169
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
>Does the following have undefined behavior?

struct X;

struct Y {

X * x_ptr;

Y ( void )
: x_ptr ( 0 )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X {};

int main ( void ) {
Y y;
}
Note that struct X is defined after struct Y is defined but before a
variable of type Y is declared. I feel that it should depend on
when/where the destructor ~Y is instantiated; but the language in the
standard is frightening and I am not sure that, left to my own devices, I
would arrive at the commonly accepted interpretation.

I just note that Comeau gives a warning and g++ accepts the code without
complaint.

You can "delete" a pointer to incomplete type. But IIRC you have
Undefined Behavior if that type then defines a non-trivial destructor.
And that was the problem with Herb Sutter's original GOTW on the PIMPL
idiom, where he employed std::auto_ptr for the implementation object.
Thanks! You are refering to [5.3.4/5], right?

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.

Now, the question becomes: which line in the program is the point of
deletion? I would think, in the snippet I posted, it's the line in the
destructor of Y, i.e., the following has UB:

#include <iostream>
#include <ostream>

struct X;

struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
Y y ( new X );
}

Thus, it makes perfect sense that it does not print anything with g++ :-)
However, I was more interested in templates anyway (posted an oversimplified
piece of code). So what about these:
A (typedef)
===========

#include <iostream>
#include <ostream>

template < typename X>
struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X;

typedef Y<XYX;

struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
YX yx ( new X );
}

B (inheritance)
===============

#include <iostream>
#include <ostream>

template < typename X>
struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X;

struct YX : public Y<X{

YX ( X * ptr = 0 )
: Y<X>( ptr )
{}

};

struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
YX yx ( new X );
}
C (position of function definition)
===================================

#include <iostream>
#include <ostream>

template < typename X>
struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X;

void f ( X * ptr = 0 ) {
Y<Xy ( ptr );
}

struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
f ( new X );
}

In my experiments with g++, all these programs print "crash me". Where is
the "point of deletion" in these programs when template instantiation
issues enter the picture? Which of the above have UB?
Best

Kai-Uwe Bux
Jul 11 '07 #2
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
[snip]
>struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {

Uh, C-ism, please don't do that Kai! Hurts me... ;-)
I did not pick that up in C, which I never learned. I like this more verbose
notation because it allows me to quickly identify function definitions as
opposed to function calls (thereby it makes the code just a little bit more
grep-able). Coming from Modula-2, I don't mind verbosity at all :-)

(just a nit: It's "Kai-Uwe"; one word, not two, note the hyphen.)

[snip]
>However, I was more interested in templates anyway (posted an
oversimplified piece of code). So what about these:
A (typedef)
===========

#include <iostream>
#include <ostream>

template < typename X>
struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X;

typedef Y<XYX;

struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
YX yx ( new X );
}

Hm. Hm. I /think/ the template isn't instantiated until 'main' (i.e.,
the typedef doesn't do anything other than introduce a name), where the
definition of X is known, and so it should be OK.

However, there's also the practical matter of compilers that don't
implement two-phase template instantiation.

>B (inheritance)
===============

#include <iostream>
#include <ostream>

template < typename X>
struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X;

struct YX : public Y<X{

I think that right here Y<Xis instantiated, with still incomplete type
X, and thus Undefined Behavior.

>>
YX ( X * ptr = 0 )
: Y<X>( ptr )
{}

};
>
struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
YX yx ( new X );
}
C (position of function definition)
===================================

#include <iostream>
#include <ostream>

template < typename X>
struct Y {

X * x_ptr;

Y ( X * ptr = 0 )
: x_ptr ( ptr )
{}

~Y ( void ) {
delete x_ptr;
}

};

struct X;

void f ( X * ptr = 0 ) {
Y<Xy ( ptr );
}

Instantiation with incomplete type X, Undefined Behavior.

>struct X {

~X ( void ) {
std::cout << "crash me\n";
}

};

int main ( void ) {
f ( new X );
}

In my experiments with g++, all these programs print "crash me".

Hm, B and C "should", as far as I understand it, exhibit UB, which of
course means they could by chance print "crash me", but in practical
terms a compiler-generated empty X destructor should be invoked.

Checking...

I get the same result as your g++-testing by using MSVC 7.1. However,
using MingW g++ 3.4.4 B and C do not print anything (and warnings are
issued for the destructor calls), while A does print "crash me" (and no
warnings). This is consistent with g++ generally being much more
standard-conforming wrt. templates than MSVC.

>Where is
the "point of deletion" in these programs when template instantiation
issues enter the picture? Which of the above have UB?

See above. I think I got it right; at least, testing above indicates
that. So, A is OK (A OK ;-)), while B and C are UB.

Thanks a lot. I also tried Comeau; and it agrees with your assesment.
Best

Kai-Uwe Bux
Jul 11 '07 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: Rick | last post by:
Hi, Does deleting an object more than one times incur undefined behavior? I think it doesn't but just making sure... thanks Rick
22
by: Neo | last post by:
Hi Folks, #include<stdio.h> int main() { int (*p); int arr; int i;
204
by: Alexei A. Frounze | last post by:
Hi all, I have a question regarding the gcc behavior (gcc version 3.3.4). On the following test program it emits a warning: #include <stdio.h> int aInt2 = {0,1,2,4,9,16}; int aInt3 =...
41
by: Alexei A. Frounze | last post by:
Seems like, to make sure that a pointer doesn't point to an object/function, NULL (or simply 0) is good enough for both kind of pointers, data pointers and function pointers as per 6.3.2.3: 3 An...
51
by: Joe Van Dyk | last post by:
When you delete a pointer, you should set it to NULL, right? Joe
50
by: Juha Nieminen | last post by:
I asked a long time ago in this group how to make a smart pointer which works with incomplete types. I got this answer (only relevant parts included): ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.