473,503 Members | 12,175 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

private destructor and templates

I have a POD type with a private destructor. There are a whole hierarchy of
derived POD types, all meant to be freed using a public member function
Destroy in the base class. I get warning C4624. I read the description,
decided that it's exactly what I want, and ignored the warning.

Now I'm trying to inherit using a template. Instead of "destructor could
not be generated because a base class destructor is inaccessible", I now
have an error C2248 <name of base destructor"cannot access private
member". Is this correct or a bug? I don't want the compiler to generate a
destructor for the base class, I won't declare any variables on the stack
and I will use the base Destroy function to deallocate it.

/**
** \brief Carries a request and any associated parameters.
**/
struct PNPEXPORT IConcurrentOperations::OpRequest abstract : OpMessage
{
...
private:
/**
** \brief Destructor, executes cleanup
**
** Calls FreeAgent to manage reference counting pAgent.
**
** Private visibility prevents declaration on the stack.
**/
~OpRequest()
{
FreeAgent();
}

public:
/**
** \brief Frees resources used by this request
**/
void Destroy( void )
{
delete this;
}
};

/**
** \param Base, should be derived from OpNotification or OpRequest
** and provide a default constructor.
**/
template<typename Base>
struct IConcurrentOperations::BufferedMessage : public Base
{...}
Oct 18 '06 #1
23 2556
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:ue****************@TK2MSFTNGP04.phx.gbl...
>I have a POD type with a private destructor. There are a whole hierarchy
of derived POD types, all meant to be freed using a public member function
Destroy in the base class. I get warning C4624. I read the description,
decided that it's exactly what I want, and ignored the warning.

Now I'm trying to inherit using a template. Instead of "destructor could
not be generated because a base class destructor is inaccessible", I now
have an error C2248 <name of base destructor"cannot access private
member". Is this correct or a bug? I don't want the compiler to generate
a destructor for the base class, I won't declare any variables on the
stack and I will use the base Destroy function to deallocate it.
Template or no, in order to derive from a class, that class needs at least
one accessible constructor and an accessible destructor. It's an MS
extension (or bug, depending on your viewpoint) that the compiler let you
get away with it in your non-template case.

Can you simply make the base-class destructor protected instead of private?

-cd
Oct 18 '06 #2
Ben Voigt wrote:
I have a POD type with a private destructor.
No such thing. PODs cannot not have private anything, PODs cannot have
user-defined destructors (8.5.1/1, 9/4).
There are a whole
hierarchy of derived POD types, all meant to be freed using a public
member function Destroy in the base class. I get warning C4624. I
read the description, decided that it's exactly what I want, and
ignored the warning.
Now I'm trying to inherit using a template. Instead of "destructor
could not be generated because a base class destructor is
inaccessible", I now have an error C2248 <name of base destructor>
"cannot access private member". Is this correct or a bug? I don't
want the compiler to generate a destructor for the base class, I
won't declare any variables on the stack and I will use the base
Destroy function to deallocate it. [...]
If the derived class does not have a private d-tor, the program will
try to provide one for you (whether you want it or not), which in turn
will try to call the base class d-tor, which you made private. So,
when deriving from a class with a private d-tor, declare your d-tor
private again.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 18 '06 #3
Ben Voigt wrote:
I have a POD type with a private destructor.
I'm sorry but it's not a POD. If you have a user defined destructor,
that's against the definition of the POD type.

If you derive from a non-POD class, and you don't supply a destructor,
the compiler will generate one for you. Just because you don't have an
explicit one, it doesn't mean you don't have one at all. The derived
destructor must be able to call the base, and if it's private, it's not
accessible. This essencially means that you can't derive from a class
that have a private destructor. This is my understanding.

Tom
Oct 18 '06 #4
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
Ben Voigt wrote:
>I have a POD type with a private destructor.

No such thing. PODs cannot not have private anything, PODs cannot have
user-defined destructors (8.5.1/1, 9/4).
Hmmm, think you're right about the destructor. However private helper
functions are certainly possible in a POD.

What do you call a class whose instances have no v-table, but isn't a POD?

>
If the derived class does not have a private d-tor, the program will
try to provide one for you (whether you want it or not), which in turn
will try to call the base class d-tor, which you made private. So,
when deriving from a class with a private d-tor, declare your d-tor
private again.
Tried that after posting and it works. Took them out again, and it works.
Slightly confused.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Oct 18 '06 #5
Ben Voigt wrote:
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
>Ben Voigt wrote:
>>I have a POD type with a private destructor.

No such thing. PODs cannot not have private anything, PODs cannot
have user-defined destructors (8.5.1/1, 9/4).

Hmmm, think you're right about the destructor. However private helper
functions are certainly possible in a POD.
_By definition_ the presence of private or protected member makes the
class non-POD. There can be no discussion or argument about it.
What do you call a class whose instances have no v-table, but isn't a
POD?
A class. A UDT, if you need to use a TLA. And what does v-table have
to do with it?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 18 '06 #6

"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
Ben Voigt wrote:
>"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
>>Ben Voigt wrote:
I have a POD type with a private destructor.

No such thing. PODs cannot not have private anything, PODs cannot
have user-defined destructors (8.5.1/1, 9/4).

Hmmm, think you're right about the destructor. However private helper
functions are certainly possible in a POD.

_By definition_ the presence of private or protected member makes the
class non-POD. There can be no discussion or argument about it.
A POD cannot have non-public variables. But it can have public member
functions, correct? Then naturally these can use private helpers
internally. Or no?

I thought a POD was anything that is a drop-in replacement for some C
struct. That means (1) layout compatible and (2) no reduced visibility for
any member. If any existing variable became hidden, it would break code
that worked on the struct. If any new variables were added, they would
break the layout. Therefore there can be no non-public variables. However
member functions and static members of any type do not affect the layout,
and do not break existing code referring to structure members, so they are
permitted, regardless of visibility.
>
>What do you call a class whose instances have no v-table, but isn't a
POD?

A class. A UDT, if you need to use a TLA. And what does v-table have
to do with it?
A v-table is what makes an object. Without a v-table, there is no
polymorphism, no RTTI, in fact no awareness of 'type'. A class without a
v-table is just an assembly of variables and functions in a naming scope,
hardly any different from a namespace.
>
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Oct 18 '06 #7
Ben Voigt wrote:
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
>Ben Voigt wrote:
>>"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
Ben Voigt wrote:
I have a POD type with a private destructor.

No such thing. PODs cannot not have private anything, PODs cannot
have user-defined destructors (8.5.1/1, 9/4).
Hmmm, think you're right about the destructor. However private
helper functions are certainly possible in a POD.

_By definition_ the presence of private or protected member makes the
class non-POD. There can be no discussion or argument about it.

A POD cannot have non-public variables. But it can have public member
functions, correct? Then naturally these can use private helpers
internally. Or no?
Are you not reading what I type here? Public member functions are OK
as long as they are not virtual. Nothing private and nothing protected.
_By definition_. If you want to challenge the definition, you should
go to 'comp.std.c++'. But I wouldn't recommend it. Learn the tools,
don't try to change them. If you need different tools, get different
tools, don't try to squeeze the existing tools into a different mold.
I thought a POD was anything that is a drop-in replacement for some C
struct. That means (1) layout compatible
Yes. C++ Standard says that the layout is pretty much known _between_
access specifiers. So, *across* access specifiers the layout is
somewhat a mystery (implementation-defined, yadda yadda).
and (2) no reduced
visibility for any member.
OK, so private and protected isn't that? Or are you trying to pull
some temporal characteristic here as well? There isn't any.
If any existing variable became hidden,
it would break code that worked on the struct.
Sigh... So, if you're writing _new_ code, it doesn't matter? What
kind of argument is that?
If any new variables
were added, they would break the layout. Therefore there can be no
non-public variables.
What if I add new public variables? Don't they break the layout of
an _existing_ struct?
However member functions and static members of
any type do not affect the layout,
Says who?
and do not break existing code
referring to structure members, so they are permitted, regardless of
visibility.
What existing code? What if I'm writing a new program altogether?
How the hell should the compiler know where the code comes from?
>>What do you call a class whose instances have no v-table, but isn't
a POD?

A class. A UDT, if you need to use a TLA. And what does v-table
have to do with it?

A v-table is what makes an object. Without a v-table, there is no
polymorphism, no RTTI, in fact no awareness of 'type'. A class
without a v-table is just an assembly of variables and functions in a
naming scope, hardly any different from a namespace.
Bull. An object is an area of computer memory, ones and zeros. There
are no RTTI, no 'type', no "awareness". Program is another set of
the same ones and zeros. See, anything can be taken to extreme and
made absurd, if one pleases. Object is a concept that exists in terms
of the program you write. Nothing more and nothing less. Same as
a class, a POD-struct, a function, a namespace, a variable, whatever.
Pull it out of its context and you can do whatever you want with it.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 18 '06 #8
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:OB**************@TK2MSFTNGP04.phx.gbl...
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
>_By definition_ the presence of private or protected member makes the
class non-POD. There can be no discussion or argument about it.

A POD cannot have non-public variables. But it can have public member
functions, correct? Then naturally these can use private helpers
internally. Or no?
Not according to the C++ standard. It's generally acknowledged that the
standard's definition of POD is overly strict. There's work underway for
the next version of the C++ standard to relax the definition of POD to more
closely match actual practice (or alternatively, come up with a new name
that describes what people intuitively think of as POD).
>
I thought a POD was anything that is a drop-in replacement for some C
struct. That means (1) layout compatible and (2) no reduced visibility
for any member. If any existing variable became hidden, it would break
code that worked on the struct. If any new variables were added, they
would break the layout. Therefore there can be no non-public variables.
However member functions and static members of any type do not affect the
layout, and do not break existing code referring to structure members, so
they are permitted, regardless of visibility.
The restriction of no non-public member functions doesn't seem very useful,
but that's what the standard says.

-cd
Oct 18 '06 #9
Carl Daniel [VC++ MVP] wrote:
Not according to the C++ standard. It's generally acknowledged that the
standard's definition of POD is overly strict. There's work underway for
the next version of the C++ standard to relax the definition of POD to more
closely match actual practice (or alternatively, come up with a new name
that describes what people intuitively think of as POD).
The restriction of no non-public member functions doesn't seem very useful,
but that's what the standard says.
Are you and Victor sure? I can see no such restriction:

8.5.1/1
"An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members
(clause 11), no base classes (clause 10), and no virtual functions (10.3)."

PODs add nothing further regarding member functions.

Tom
Oct 19 '06 #10
Victor Bazarov wrote:
Ben Voigt wrote:
>"Victor Bazarov" <v.********@comAcast.netwrote in message
news:eh**********@news.datemas.de...
>>Ben Voigt wrote:
I have a POD type with a private destructor.
No such thing. PODs cannot not have private anything, PODs cannot
have user-defined destructors (8.5.1/1, 9/4).
Hmmm, think you're right about the destructor. However private helper
functions are certainly possible in a POD.

_By definition_ the presence of private or protected member makes the
class non-POD. There can be no discussion or argument about it.
Citation please. I think private member functions (and private static
member variables) are allowed in PODs and aggregates.

Tom
Oct 19 '06 #11
Ben Voigt wrote:
I have a POD type with a private destructor. There are a whole hierarchy of
derived POD types, all meant to be freed using a public member function
Destroy in the base class. I get warning C4624. I read the description,
decided that it's exactly what I want, and ignored the warning.
As said by others, your class becomes a non-POD as soon as you declare a
destructor. Additionally, derived classes are never POD types.
Now I'm trying to inherit using a template. Instead of "destructor could
not be generated because a base class destructor is inaccessible", I now
have an error C2248 <name of base destructor"cannot access private
member". Is this correct or a bug?
It depends on whether your code is attempting to use the derived class
destructor (e.g. a call to delete will do that).

I don't want the compiler to generate a
destructor for the base class,
But you've written a destructor - it even does something (calls
FreeAgent();).

I won't declare any variables on the stack
and I will use the base Destroy function to deallocate it.
If you won't declare any variables on the stack, just drop your
declaration of a destructor - it isn't needed. Instead, to prevent
accidental external delete calls, you could declare a class operator new
public and operator delete protected, which shouldn't affect your POD
status. Instead, you could make the Destroy function call FreeAgent()
before delete this.
>
/**
** \brief Carries a request and any associated parameters.
**/
struct PNPEXPORT IConcurrentOperations::OpRequest abstract : OpMessage
{
...
private:
/**
** \brief Destructor, executes cleanup
**
** Calls FreeAgent to manage reference counting pAgent.
**
** Private visibility prevents declaration on the stack.
**/
~OpRequest()
{
FreeAgent();
}

public:
/**
** \brief Frees resources used by this request
**/
void Destroy( void )
{
delete this;
That is problematic, since your destructor isn't virtual. You can't
destroy an object through a base class pointer unless it has a virtual
destructor.
}
};

/**
** \param Base, should be derived from OpNotification or OpRequest
** and provide a default constructor.
**/
template<typename Base>
struct IConcurrentOperations::BufferedMessage : public Base
{...}
What are you trying to do? We might be able to suggest a workable design.

Tom
Oct 19 '06 #12
Tom Widmer [VC++ MVP] wrote:
Carl Daniel [VC++ MVP] wrote:
>Not according to the C++ standard. It's generally acknowledged that
the standard's definition of POD is overly strict. There's work
underway for the next version of the C++ standard to relax the
definition of POD to more closely match actual practice (or
alternatively, come up with a new name that describes what people
intuitively think of as POD).
>The restriction of no non-public member functions doesn't seem very
useful, but that's what the standard says.

Are you and Victor sure? I can see no such restriction:

8.5.1/1
"An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members
(clause 11), no base classes (clause 10), and no virtual functions
(10.3)."
PODs add nothing further regarding member functions.
Well. now I'm going to have to look! At the time, I didn't have my copy of
the standard handy, Victor's stsatements rang true to me, and Victor is
rarely wrong about such things.

9/4 says:

"A POD-struct is an aggregate class that has no non-static data members of
type pointer to member, non-POD-struct, non-POD-union (or array of such
types) or reference, and has no user-defined copy assignment operator and no
user-defined destructor."

So the OP's class is not a POD because it has a user-defined destructor. My
statement above about no non-public member functions is incorrect - only
destructors and copy-assignment operators are mentioned in the definition of
POD (above and beyond aggregate) and there's no special consideration for
non-public function members at all.

-cd

Oct 19 '06 #13
> If any new variables
were added, they would break the layout. Therefore there can be no
non-public variables.

What if I add new public variables? Don't they break the layout of
an _existing_ struct?
Still a POD, because it is layout compatible with some C struct, namely the
C struct that also has those public variables added.
>
> However member functions and static members of
any type do not affect the layout,

Says who?
Says me. Non-virtual member functions and static members of any type add no
per-instance overhead, and occupy no space in the layout.
>
>and do not break existing code
referring to structure members, so they are permitted, regardless of
visibility.

What existing code? What if I'm writing a new program altogether?
What does "Drop-in replacement" mean to you? A POD means you can
reinterpret_cast back and forth at will with the corresponding C struct.
You can create an instance of the POD, and pass it by reference to a C
function, and vice versa you can receive it from a C function, cast it as
the POD, and call POD member functions on it without losing type-safety.
You can also typedef the POD type in place of the old struct and not have
any visibility errors.
How the hell should the compiler know where the code comes from?
POD is not a compiler concept. The compiler only distinguishes between "has
a v-table" and "doesn't".
>>
A v-table is what makes an object. Without a v-table, there is no
polymorphism, no RTTI, in fact no awareness of 'type'. A class
without a v-table is just an assembly of variables and functions in a
naming scope, hardly any different from a namespace.

Bull. An object is an area of computer memory, ones and zeros. There
are no RTTI, no 'type', no "awareness". Program is another set of
the same ones and zeros. See, anything can be taken to extreme and
made absurd, if one pleases. Object is a concept that exists in terms
of the program you write. Nothing more and nothing less. Same as
a class, a POD-struct, a function, a namespace, a variable, whatever.
Pull it out of its context and you can do whatever you want with it.
An object class has a v-table uniquely identifying the type. Every instance
has a pointer to this v-table. Therefore the instance has an exact type,
known at runtime, for which that v-table is created. POD types have no
v-table.
Oct 19 '06 #14
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:OM*************@TK2MSFTNGP05.phx.gbl...
POD is not a compiler concept. The compiler only distinguishes between
"has a v-table" and "doesn't".
You're speaking pragmatically, and Victor is speaking theoretically. POD is
defined by the C++ standard to have a specific meaning, whether than meaning
has any concrete ramifications in the compiler or not. While it's true that
under VC++ only the presense of virtual functions or virtual base classes
affects object layout, there's nothing that requires a C++ compiler to work
that way.

What you call a POD is closer to what most programmers consider a "POD" - a
definition that's less restrictive than the one in the C++ standard.

-cd
Oct 19 '06 #15

"Tom Widmer [VC++ MVP]" <to********@hotmail.comwrote in message
news:OZ**************@TK2MSFTNGP05.phx.gbl...
Ben Voigt wrote:
>I have a POD type with a private destructor. There are a whole hierarchy
of derived POD types, all meant to be freed using a public member
function Destroy in the base class. I get warning C4624. I read the
description, decided that it's exactly what I want, and ignored the
warning.

As said by others, your class becomes a non-POD as soon as you declare a
destructor. Additionally, derived classes are never POD types.
Ok, I'm not really caring about being POD. I care about being able to use
and destroy it non-virtually.
>
>Now I'm trying to inherit using a template. Instead of "destructor could
not be generated because a base class destructor is inaccessible", I now
have an error C2248 <name of base destructor"cannot access private
member". Is this correct or a bug?

It depends on whether your code is attempting to use the derived class
destructor (e.g. a call to delete will do that).
One of the derived classes had a gcroot member (to carry System::Exception
objects between threads). Not calling the destructor on that would be bad,
so now I'm explicitly setting it to nullptr before letting the base class
destroy it. What I will probably end up doing is formatting an error
message using Environment::StackTrace and passing that as raw UNICODE
characters.

I'm passing information between threads (one managed, one not) and if
something gets mixed up so there are still messages in flight (PostMessage)
when I call DestroyWindow, I'd like to not lose anything more than just
leaking a small buffer object (up to 200 bytes) on the heap. Since the .NET
gc can't track pointers inside message queues, this is how I've chosen to do
it.

Incidentally, this is why it's very important to me to avoid virtual calls
to anything. Anyone could drop messages into my queue with an arbitrary
LPARAM.

Toward that end, is it possible to filter WM_TIMER messages from being
passed to DispatchMessage in a .NET app?
>
I don't want the compiler to generate a
>destructor for the base class,

But you've written a destructor - it even does something (calls
FreeAgent();).
Sorry, I meant I didn't want the compiler to generate destructors for the
derived classes.
>
I won't declare any variables on the stack
>and I will use the base Destroy function to deallocate it.

If you won't declare any variables on the stack, just drop your
declaration of a destructor - it isn't needed. Instead, to prevent
accidental external delete calls, you could declare a class operator new
public and operator delete protected, which shouldn't affect your POD
Sadly, protected operator delete causes a compile error at every use of
operator new.
I think this is in case a constructor throws -- the instance isn't
constructed at that point, so the destructor needn't be accessible. But
operator delete needs to be. (/me frowns)
Actually that is it, because marking derived constructors nothrow with
throw() makes the error go away.
status. Instead, you could make the Destroy function call FreeAgent()
before delete this.
Ok, doing that. Removing destructor. I guess that makes declaration on the
stack possible again, which isn't really a problem although it's never
necessary.
>
>>
/**
** \brief Carries a request and any associated parameters.
**/
struct PNPEXPORT IConcurrentOperations::OpRequest abstract : OpMessage
{
...
private:
/**
** \brief Destructor, executes cleanup
**
** Calls FreeAgent to manage reference counting pAgent.
**
** Private visibility prevents declaration on the stack.
**/
~OpRequest()
{
FreeAgent();
}

public:
/**
** \brief Frees resources used by this request
**/
void Destroy( void )
{
delete this;

That is problematic, since your destructor isn't virtual. You can't
destroy an object through a base class pointer unless it has a virtual
destructor.
If all derived types just add additional POD fields, then I wouldn't need to
destroy it virtually.
>
> }
};

/**
** \param Base, should be derived from OpNotification or OpRequest
** and provide a default constructor.
**/
template<typename Base>
struct IConcurrentOperations::BufferedMessage : public Base
{...}

What are you trying to do? We might be able to suggest a workable design.

Tom

Oct 19 '06 #16
Ben Voigt wrote:
POD is not a compiler concept. The compiler only distinguishes between "has
a v-table" and "doesn't".
Have you seen the intrinsic __is_pod(T) in VS2005?

Tom
Oct 20 '06 #17
Ben Voigt wrote:
"Tom Widmer [VC++ MVP]" <to********@hotmail.comwrote in message
news:OZ**************@TK2MSFTNGP05.phx.gbl...
>Ben Voigt wrote:
>>I have a POD type with a private destructor. There are a whole hierarchy
of derived POD types, all meant to be freed using a public member
function Destroy in the base class. I get warning C4624. I read the
description, decided that it's exactly what I want, and ignored the
warning.
As said by others, your class becomes a non-POD as soon as you declare a
destructor. Additionally, derived classes are never POD types.

Ok, I'm not really caring about being POD. I care about being able to use
and destroy it non-virtually.
You can't do that portably even for POD types, unless you switch from
new/delete to malloc/free. More on that further down.
>>Now I'm trying to inherit using a template. Instead of "destructor could
not be generated because a base class destructor is inaccessible", I now
have an error C2248 <name of base destructor"cannot access private
member". Is this correct or a bug?
It depends on whether your code is attempting to use the derived class
destructor (e.g. a call to delete will do that).

One of the derived classes had a gcroot member (to carry System::Exception
objects between threads). Not calling the destructor on that would be bad,
so now I'm explicitly setting it to nullptr before letting the base class
destroy it. What I will probably end up doing is formatting an error
message using Environment::StackTrace and passing that as raw UNICODE
characters.

I'm passing information between threads (one managed, one not) and if
something gets mixed up so there are still messages in flight (PostMessage)
when I call DestroyWindow, I'd like to not lose anything more than just
leaking a small buffer object (up to 200 bytes) on the heap. Since the .NET
gc can't track pointers inside message queues, this is how I've chosen to do
it.
That is in violation of the docs for PostMessage:
"If you send a message in the range below WM_USER to the asynchronous
message functions (PostMessage, SendNotifyMessage, and
SendMessageCallback), its message parameters cannot include pointers.
Otherwise, the operation will fail. The functions will return before the
receiving thread has had a chance to process the message and the sender
will free the memory before it is used."

In other words, you shouldn't fire off pointers to a window and expect
the window to delete them. Instead, you should use SendMessage, and
delete them yourself. This then avoids the whole issue.
Incidentally, this is why it's very important to me to avoid virtual calls
to anything. Anyone could drop messages into my queue with an arbitrary
LPARAM.
I don't understand that.
Toward that end, is it possible to filter WM_TIMER messages from being
passed to DispatchMessage in a .NET app?
Sorry, I've no .NET expertise.
>I don't want the compiler to generate a
>>destructor for the base class,
But you've written a destructor - it even does something (calls
FreeAgent();).

Sorry, I meant I didn't want the compiler to generate destructors for the
derived classes.
Ahh, ok.
> I won't declare any variables on the stack
>>and I will use the base Destroy function to deallocate it.
If you won't declare any variables on the stack, just drop your
declaration of a destructor - it isn't needed. Instead, to prevent
accidental external delete calls, you could declare a class operator new
public and operator delete protected, which shouldn't affect your POD

Sadly, protected operator delete causes a compile error at every use of
operator new.
I think this is in case a constructor throws -- the instance isn't
constructed at that point, so the destructor needn't be accessible. But
operator delete needs to be. (/me frowns)
Actually that is it, because marking derived constructors nothrow with
throw() makes the error go away.
Ahh, yes. I didn't realise the derived classes have destructors (which
is yet another violation of the requirements on POD data).
>That is problematic, since your destructor isn't virtual. You can't
destroy an object through a base class pointer unless it has a virtual
destructor.

If all derived types just add additional POD fields, then I wouldn't need to
destroy it virtually.
Calling delete with the wrong type is illegal C++, unless the destructor
is virtual. It happens to work on some compilers and versions, but not
necessarily all, since the compiler is at liberty to use the type of the
deleted object to determine the size of the allocation that created it.
Also, a debugging implementation might check that constructed objects
have their destructors run.

Based on what you've said, the easiest option would be to stop using
PostMessage and instead destroy messages at the sending site. If you
can't do that, you are probably best off moving to using real POD
objects, dropping your use of new and delete expressions, and using
::operator new and ::operator delete (or malloc and free), which work
fine with raw memory, and don't care about pointer types or destructors.
If you want more standards compliant code, you could replace
constructors with initialization functions, and drop inheritence
entirely (making your Destroy function a free function).

It seems to me that you're conflating OO and C style programming in an
unnecessary and confusing way.

Tom
Oct 20 '06 #18
"Tom Widmer wrote:
>I'm passing information between threads (one managed, one
not) and if something gets mixed up so there are still
messages in flight (PostMessage) when I call
DestroyWindow, I'd like to not lose anything more than
just leaking a small buffer object (up to 200 bytes) on
the heap. Since the .NET gc can't track pointers inside
message queues, this is how I've chosen to do it.

That is in violation of the docs for PostMessage:
"If you send a message in the range below WM_USER to the
asynchronous message functions (PostMessage,
SendNotifyMessage, and SendMessageCallback), its message
parameters cannot include pointers. Otherwise, the
operation will fail. The functions will return before the
receiving thread has had a chance to process the message
and the sender will free the memory before it is used."

In other words, you shouldn't fire off pointers to a
window and expect the window to delete them. Instead, you
should use SendMessage, and delete them yourself. This
then avoids the whole issue.

I think you're interpreting this paragraph in a too strict
way. It says that if you want pointer marshalling to work
(for messages < WM_USER), then don't use asynchronous
message functions. You still can use pointers as message
parameters for messages above WM_USER. Just don't expect any
free marshalling services from system. As long as you post
pointers within the same process and free them at the right
moment there is no problem with PostMessage.
Alex
Oct 20 '06 #19

"Tom Widmer [VC++ MVP]" <to********@hotmail.comwrote in message
news:eZ**************@TK2MSFTNGP05.phx.gbl...
Ben Voigt wrote:
>POD is not a compiler concept. The compiler only distinguishes between
"has a v-table" and "doesn't".

Have you seen the intrinsic __is_pod(T) in VS2005?
And finally we discover where Victor got his incorrect definition of POD.

Compare http://msdn2.microsoft.com/en-us/library/ms177194.aspx vs
http://home.twcny.rr.com/hinnant/cpp...in_traits.html

Though the MSVC++ definition wrongly allows user-defined destructors...
>
Tom

Oct 20 '06 #20
>I'm passing information between threads (one managed, one not) and if
>something gets mixed up so there are still messages in flight
(PostMessage) when I call DestroyWindow, I'd like to not lose anything
more than just leaking a small buffer object (up to 200 bytes) on the
heap. Since the .NET gc can't track pointers inside message queues, this
is how I've chosen to do it.

That is in violation of the docs for PostMessage:
"If you send a message in the range below WM_USER to the asynchronous
message functions (PostMessage, SendNotifyMessage, and
SendMessageCallback), its message parameters cannot include pointers.
Otherwise, the operation will fail. The functions will return before the
receiving thread has had a chance to process the message and the sender
will free the memory before it is used."
My message isn't below WM_USER. It is however, exactly equal to WM_USER,
which raises the concern that some other app might also use it, and might
not be careful where it sends messages.
>
In other words, you shouldn't fire off pointers to a window and expect the
window to delete them. Instead, you should use SendMessage, and delete
them yourself. This then avoids the whole issue.
Since I'm implementing a user message where I control both ends, having the
window delete the pointers is completely feasible. SendMessage would not
be, since it would block my worker thread.
>
>Incidentally, this is why it's very important to me to avoid virtual
calls to anything. Anyone could drop messages into my queue with an
arbitrary LPARAM.

I don't understand that.
(*(LPFUNCTION)lParam)() or ((CSomething*)lParam)->method() with method being
virtual, is a huge security hole.

((CSomething*)lParam)->method() where method is non-virtual is quite safe
however, provided method doesn't implicitly trust its this pointer. Since I
am only reading from the structure and have that wrapped in an SEH block, I
think I'm ok. The idea of freeing that pointer still troubles me somewhat.
A message authentication code of some type might be in order.
>
>Toward that end, is it possible to filter WM_TIMER messages from being
passed to DispatchMessage in a .NET app?

Sorry, I've no .NET expertise.
The issue is that DispatchMessage handles WM_TIMER in exactly the broken
method described above.
>
>>I don't want the compiler to generate a
destructor for the base class,
But you've written a destructor - it even does something (calls
FreeAgent();).

Sorry, I meant I didn't want the compiler to generate destructors for the
derived classes.

Ahh, ok.
>> I won't declare any variables on the stack
and I will use the base Destroy function to deallocate it.
If you won't declare any variables on the stack, just drop your
declaration of a destructor - it isn't needed. Instead, to prevent
accidental external delete calls, you could declare a class operator new
public and operator delete protected, which shouldn't affect your POD

Sadly, protected operator delete causes a compile error at every use of
operator new.
I think this is in case a constructor throws -- the instance isn't
constructed at that point, so the destructor needn't be accessible. But
operator delete needs to be. (/me frowns)
Actually that is it, because marking derived constructors nothrow with
throw() makes the error go away.

Ahh, yes. I didn't realise the derived classes have destructors (which is
yet another violation of the requirements on POD data).
I made operator delete protected before deleting the private destructor,
which certainly contributed to the problem. But all of my constructors
needed to be declared non-throwing anyway.
>
>>That is problematic, since your destructor isn't virtual. You can't
destroy an object through a base class pointer unless it has a virtual
destructor.

If all derived types just add additional POD fields, then I wouldn't need
to destroy it virtually.

Calling delete with the wrong type is illegal C++, unless the destructor
is virtual. It happens to work on some compilers and versions, but not
necessarily all, since the compiler is at liberty to use the type of the
deleted object to determine the size of the allocation that created it.
Also, a debugging implementation might check that constructed objects have
their destructors run.

Based on what you've said, the easiest option would be to stop using
PostMessage and instead destroy messages at the sending site. If you
Can't do that, the message passing vs remote procedure call distinction is
important here.
can't do that, you are probably best off moving to using real POD objects,
dropping your use of new and delete expressions, and using ::operator new
and ::operator delete (or malloc and free), which work
I'd defined my own operator new and operator delete in the base class as
you'll recall. I had used
static void* operator new(size_t bytes)
{
return new char[bytes];
}

static void operator delete(void* p)
{
delete [] p;
}

I'll go ahead and change these to call malloc and free. Would that be legal
then?

Some derived classes do override operator new with a placement parameter
indicating the size of an variably-sized buffer. They delegate to the base
class operator new after adjusting the size of the allocation. Is that also
highly suspect?
fine with raw memory, and don't care about pointer types or destructors.
If you want more standards compliant code, you could replace constructors
with initialization functions, and drop inheritence entirely (making your
Destroy function a free function).
I could do that by making the first member of each structure an instance of
what's currently the base class, in the same fashion that the Windows API
does structure polymorphism. But what would that change, besides having to
explicitly specify the name of that structure to use its members?

I take it you are suggesting allocating structures with
(derived_type*) base_type::Alloc(sizeof derived_type + extra_buffer_bytes)
>
It seems to me that you're conflating OO and C style programming in an
unnecessary and confusing way.
Would you prefer I use a POD union? That has really bad locality of
definition which translates into unmaintainability.

C style programming can be object oriented, and C++ can be procedural.
Really C++ is just a lot of syntactic sugar on top of C, plus some really
nifty things like templates.

I find it really handy to have a polymorphic set of structures that share
the initial few members and then each add several more. This is possible in
C, but really ugly. Take a look at any code using BITMAPCOREHEADER and it's
derivatives BITMAPINFOHEADER, BITMAPV4HEADER, BITMAPV5HEADER in the context
of BITMAPINFO and you'll see the ugliness I'm trying to avoid.

I'm sorry to hear that what I'm doing is broken, because maintaining
duplicate code ala BITMAP*HEADER isn't very appealing (did we really need
four different declarations of the width member with four different names?).
>
Tom

Oct 20 '06 #21
Ben Voigt wrote:
>That is in violation of the docs for PostMessage:
"If you send a message in the range below WM_USER to the asynchronous
message functions (PostMessage, SendNotifyMessage, and
SendMessageCallback), its message parameters cannot include pointers.
Otherwise, the operation will fail. The functions will return before the
receiving thread has had a chance to process the message and the sender
will free the memory before it is used."

My message isn't below WM_USER. It is however, exactly equal to WM_USER,
which raises the concern that some other app might also use it, and might
not be careful where it sends messages.
>In other words, you shouldn't fire off pointers to a window and expect the
window to delete them. Instead, you should use SendMessage, and delete
them yourself. This then avoids the whole issue.

Since I'm implementing a user message where I control both ends, having the
window delete the pointers is completely feasible. SendMessage would not
be, since it would block my worker thread.
A strict reading of the PostMessage docs for VC2005 implies it is
illegal, though I don't understand why it should be illegal, since, as
you say, you have control of the pointers at both ends.
>>Incidentally, this is why it's very important to me to avoid virtual
calls to anything. Anyone could drop messages into my queue with an
arbitrary LPARAM.
I don't understand that.

(*(LPFUNCTION)lParam)() or ((CSomething*)lParam)->method() with method being
virtual, is a huge security hole.

((CSomething*)lParam)->method() where method is non-virtual is quite safe
however, provided method doesn't implicitly trust its this pointer. Since I
am only reading from the structure and have that wrapped in an SEH block, I
think I'm ok. The idea of freeing that pointer still troubles me somewhat.
A message authentication code of some type might be in order.
I see, that seems sensible to avoid.
>Ahh, yes. I didn't realise the derived classes have destructors (which is
yet another violation of the requirements on POD data).
Sorry, I meant constructors!
>
I made operator delete protected before deleting the private destructor,
which certainly contributed to the problem. But all of my constructors
needed to be declared non-throwing anyway.
>>>That is problematic, since your destructor isn't virtual. You can't
destroy an object through a base class pointer unless it has a virtual
destructor.
If all derived types just add additional POD fields, then I wouldn't need
to destroy it virtually.
Calling delete with the wrong type is illegal C++, unless the destructor
is virtual. It happens to work on some compilers and versions, but not
necessarily all, since the compiler is at liberty to use the type of the
deleted object to determine the size of the allocation that created it.
Also, a debugging implementation might check that constructed objects have
their destructors run.

Based on what you've said, the easiest option would be to stop using
PostMessage and instead destroy messages at the sending site. If you
Can't do that, the message passing vs remote procedure call distinction is
important here.
>can't do that, you are probably best off moving to using real POD objects,
dropping your use of new and delete expressions, and using ::operator new
and ::operator delete (or malloc and free), which work

I'd defined my own operator new and operator delete in the base class as
you'll recall. I had used
static void* operator new(size_t bytes)
{
return new char[bytes];
}

static void operator delete(void* p)
{
delete [] p;
}

I'll go ahead and change these to call malloc and free. Would that be legal
then?
An alternative fix is:
static void operator delete(void* p)
{
delete [] static_cast<char*>(p);
}

The point is, you should not be calling constructors if you don't match
the constructor calls with equivalent destructor calls. To avoid
constructor calls, you shouldn't use new-expressions.
Some derived classes do override operator new with a placement parameter
indicating the size of an variably-sized buffer. They delegate to the base
class operator new after adjusting the size of the allocation. Is that also
highly suspect?
>fine with raw memory, and don't care about pointer types or destructors.
If you want more standards compliant code, you could replace constructors
with initialization functions, and drop inheritence entirely (making your
Destroy function a free function).

I could do that by making the first member of each structure an instance of
what's currently the base class, in the same fashion that the Windows API
does structure polymorphism. But what would that change, besides having to
explicitly specify the name of that structure to use its members?
Well, there are guarantees regarding the layout of members of PODs. With
derivation, there is no guarantee. For example, derived class members
might be before or after base class members in memory. At the extreme,
base class members could be referenced in the derived class by a
pointer! e.g.

struct Base
{
int i;
};

class Derived: public Base
{
int derivedMember1;
Base* __hiddenBasePointer;

void f()
{
i = 10;
//translates to __hiddenBasePointer->i = 10;
}
};

Obviously, the implicitly generated constructors and destructors would
have to handle failure proof allocating and deleting of the pointer.

Note I don't know any compiler that does this in practice! I'm just
highlighting the lack of guarantees you get when you switch to using
derivation.
I take it you are suggesting allocating structures with
(derived_type*) base_type::Alloc(sizeof derived_type + extra_buffer_bytes)
Well, I'd wrap that in a call:

derived_type* p = derived_type::Alloc();
//...
base_type::Free(p);

Using the curiously recurring template pattern, you could even avoid
having to write the Alloc function in each derived class.
>It seems to me that you're conflating OO and C style programming in an
unnecessary and confusing way.

Would you prefer I use a POD union? That has really bad locality of
definition which translates into unmaintainability.
No, I don't think that would be better.
C style programming can be object oriented, and C++ can be procedural.
Really C++ is just a lot of syntactic sugar on top of C, plus some really
nifty things like templates.
Right, I suppose I mean that if you don't want to go the C++ OO route,
for whatever reason, you should go the C OO route.
I find it really handy to have a polymorphic set of structures that share
the initial few members and then each add several more. This is possible in
C, but really ugly. Take a look at any code using BITMAPCOREHEADER and it's
derivatives BITMAPINFOHEADER, BITMAPV4HEADER, BITMAPV5HEADER in the context
of BITMAPINFO and you'll see the ugliness I'm trying to avoid.
Yes, I'm familiar with those structs.
I'm sorry to hear that what I'm doing is broken, because maintaining
duplicate code ala BITMAP*HEADER isn't very appealing (did we really need
four different declarations of the width member with four different names?).
Well, the code will probably work on most compilers even with
inheritence, and if you go the Alloc/Destroy route (internally using
malloc/free or ::operator new/delete directly and *not* new/delete
expressions, to avoid invoking destructors implicitly), then any
problems with destructors should go away.

e.g.

/**
** \brief Carries a request and any associated parameters.
**/
struct PNPEXPORT IConcurrentOperations::OpRequest abstract : OpMessage
{
//...
public:
/**
** \brief Frees resources used by this request
**/
void Destroy( void )
{
FreeAgent();
::operator delete(this);
}

protected:
static void* Alloc(std::size_t size)
{
return ::operator new(size);
}
};

template <class Derived, class Base>
struct AllocHelper: public Base
{
static Derived* Alloc()
{
Derived* d = static_cast<Derived*>(Base::Alloc(sizeof(Derived)) );
d->Init();
//or if you want to stick with constructors:
//new (d) Derived();
return d;
}

//you could add templated overloads with parameters.
};

/**
** \param Base, should be derived from OpNotification or OpRequest
** and provide a default constructor.
**/
template<typename Base>
struct IConcurrentOperations::BufferedMessage
: public AllocHelper<IConcurrentOperations::BufferedMessage <Base>, Base>
{...}

or something like that.

Tom
Oct 20 '06 #22
A strict reading of the PostMessage docs for VC2005 implies it is illegal,
though I don't understand why it should be illegal, since, as you say, you
have control of the pointers at both ends.
Rather the strict reading says that the warnings don't apply to me because
I'm using WM_USER, not "a message in the range below WM_USER".
>
The point is, you should not be calling constructors if you don't match
the constructor calls with equivalent destructor calls. To avoid
constructor calls, you shouldn't use new-expressions.
If I define operator new myself and have no data members with non-trivial
constructor, then the only extra code being executed are my constructors,
right?
/**
** \param Base, should be derived from OpNotification or OpRequest
** and provide a default constructor.
**/
template<typename Base>
struct IConcurrentOperations::BufferedMessage
: public AllocHelper<IConcurrentOperations::BufferedMessage <Base>, Base>
{...}
That still needs to be explicitly specified for every concrete derived type
:(
>
or something like that.

Tom
Is this page accurate:
http://www.informit.com/guides/conte...eqNum=196&rl=1
Oct 20 '06 #23
Ben Voigt wrote:
>A strict reading of the PostMessage docs for VC2005 implies it is illegal,
though I don't understand why it should be illegal, since, as you say, you
have control of the pointers at both ends.

Rather the strict reading says that the warnings don't apply to me because
I'm using WM_USER, not "a message in the range below WM_USER".
Ahh, I now see that the docs only apply to system messages, apologies
for the confusion.
>The point is, you should not be calling constructors if you don't match
the constructor calls with equivalent destructor calls. To avoid
constructor calls, you shouldn't use new-expressions.

If I define operator new myself and have no data members with non-trivial
constructor, then the only extra code being executed are my constructors,
right?
Typically, though obviously the compiler can add any extra code it
wants. e.g. in debug builds, the constructors might initialize the
objects memory to 0xDEADBEEF or something before running any other
constructor code, or the object might be registered with a "live
objects" registry.

However, the reason not to use new-expressions is to avoid having to use
delete-expressions, which invoke destructors. If you instead allocate
the memory manually (with malloc, ::operator new or even class::operator
new), and then use placement new or an init function to initialize the
object, then the errors you were getting with destructors will not occur
on any compiler.
>/**
** \param Base, should be derived from OpNotification or OpRequest
** and provide a default constructor.
**/
template<typename Base>
struct IConcurrentOperations::BufferedMessage
: public AllocHelper<IConcurrentOperations::BufferedMessage <Base>, Base>
{...}

That still needs to be explicitly specified for every concrete derived type
:(
An alternative would be to stick with the current inheritence heirarchy,
and create a free function (or a member of Base if you prefer):

template <class Derived>
Derived* Alloc()
{
void* p = Base::Alloc(sizeof(Derived));
return new(p) Derived();
}

and then the derived classes just allocate themselves with:

Derived* d = Alloc<Derived>();
rather than with
Derived* d = new Derived();

Again, you can avoid going near the destructors with your Free function,
since you won't use a delete-expression (but rather ::operator delete or
free()). You can also declare (but not define) a private operator new
and delete in Base, to make sure no one accidentally does a new or
delete on the derived types.
Is this page accurate:
http://www.informit.com/guides/conte...eqNum=196&rl=1
Well, it doesn't mention that the location of base objects is
unspecified. It has them directly preceding derived objects, but that
isn't required - they may actually be held in a completely different
part of memory. Only POD objects need use contiguous storage, though in
practice I've not heard of an implementation taking advantage of this
allowance. I suppose, in theory, an implementation could notice that the
base class is constant and can only take a limited set of values,
generate one sub-object for each possible value, and then put a pointer
to the relevent base class sub-object in the derived class on construction.

Tom
Oct 23 '06 #24

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

Similar topics

3
21367
by: Rajesh Garg | last post by:
Can we have private constructors and destructors? IF yes what is the use of such constructors or destructors.....in the sense where can these be implemented in a system................. I have...
3
8814
by: Arve Sollie | last post by:
class myClass { private: int refCount; ~myClass(); public: myClass(); void incRefCount() { ++refCount; }
1
3303
by: Steven T. Hatton | last post by:
ISO/IEC 14882:2003: "5.2.4 Pseudo destructor call The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class...
6
2552
by: pragtideep | last post by:
I am trying to understand the following code kindly help me #include<iostream> using namespace std; class base { private: ~base() {cout << "This is base destructor"<<endl ;} friend class...
6
2180
by: VSP | last post by:
Hello, I am just implementing singleton pattern in various ways. In one implementation I created a static member and returning that static member in the getInstance() function. I have made...
2
2481
by: algatt | last post by:
Hello, I am trying to compile the TPIE files but there is a file that's constantly giving errors about the templates. I am using gcc 3.4.5 on Eclipse using Windows XP. The following is the code of...
3
1701
by: nick4ng | last post by:
If I have a templated constructor, there is a way to know, at compile time, the instance when compiling the destructor? To be clearer my problem is that I have a templated constructor that is...
7
4266
by: Rahul | last post by:
Hi Everyone, I was trying to implement a final class and i start having the destructor of the final class as private, class A { ~A() { printf("destructor invoked\n");
23
2604
by: Chris Gordon-Smith | last post by:
Hello All I have a base class called Action_Request, and a set of classes corresponding to different kinds of Action_Request, each of which inherits from Action_Request. Eg:- class ...
0
7193
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
7067
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
7264
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7449
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...
1
4992
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4666
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
1495
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
728
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
371
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.