Topic: Deallocation function definition required?
Author: "Wil Evers" <wil@ittpub.nl>
Date: 1997/05/06 Raw View
Hi,
Paul D. DeRocco <strip_these_words_pderocco@ix.netcom.com> wrote in article
<33698E88.329F@ix.netcom.com>...
> But they report an unresolved external because they implement it in a
> manner that is reasonable, but in which it would be extremely difficult
> to suppress that warning.
In all the implementations I know of, an undefined external is not just a
warning one can decide to ignore and continue business as usual. It is a
fatal error precluding the generation of the program.
> For instance, as someone (perhaps you?)
> pointed out, the Borland compiler generates a reference to operator new
> in _every_ constructor, and to operator delete in _every_ destructor,
> even if non-virtual, since Borland chose to have a single function serve
> as both constructor and allocator/constructor, and a single function as
> both destructor and destructor/deallocator, based on a hidden flag
> parameter passed by the compiler. This shortens the code at the call
> site. However, having done this, there's no easy way (that I can see) to
> suppress the unresolved external from the linker.
In many cases, I believe the 'Borland trick' is indeed a reasonable
implementation, provided the generated code refers to the global operators
new/new[]/delete/delete[], which are part of the standard library and are
therefore required to be defined anyway.
However, including a call to a *class-specific* operator
new/new[]/delete/delete[] in the generated code for constructors and
destructors causes a real problem, especially if these are declared private
and not intended to be used. The first time I was confronted with such an
undefined external, it caused a serious attack of paranoia.
Having said that, I don't see how we can do without such a generated call
in the presence of a virtual destructor, but I'm still hoping someone will
point out how it can be avoided. (I believe we may also have an
accessibility issue here: what if a derived class declares a private
operator delete and its base class has a virtual destructor?).
> You're right that the standard shouldn't be ambiguous. I wouldn't object
> if it required the operator, as long as it didn't prohibit an
> implementation from not enforcing the requirement if the implementation
> is able to do without the definition.
I don't get this: if no portable and reasonably efficient implementation is
possible without such a definition, then why not simply require it?
Conversely, if a reasonable implementation is possible without the need for
such a definition, then why bother the user by requiring one?
- Wil
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/05/07 Raw View
"Wil Evers" <wil@ittpub.nl> writes:
|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote in article
|> <rf5d8r69vam.fsf@vx.cit.alcatel.fr>...
|> >
|> > "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com> writes:
|> >
|> > |> You're right that the standard shouldn't be ambiguous. I wouldn't
|> > |> object if it required the operator, as long as it didn't prohibit an
|> > |> implementation from not enforcing the requirement if the
|> implementation
|> > |> is able to do without the definition.
|> >
|> > I see two alternatives that the standard could adopt: either it could
|> > systematically require the implementation, even if it was never used,
|> > much as it does with virtual functions, or it could simple say that
|> > using it if it isn't defined is undefined behavior, much like calling a
|> > pure virtual function virtually (e.g.: from within a constructor). Note
|> > that in the latter case, most compilers will give you a run-time error
|> > message and abort; I would expect a similar solution to be adopted in
|> > the case of the undefined destructor.
|>
|> Practically speaking, I don't think your second alternative is easy to
|> implement. The current draft requires that if a class has a virtual
|> destructor, the operator delete to use is found at run-time, based on the
|> object's most derived type. To me, this implies that a reference to that
|> operator delete must somehow be present in the emitted code. Therefore, I
|> would expect a link-time error when it is not defined, and I don't see how
|> such an error could be postponed until run-time without invoking some sort
|> of dynamic linking magic.
|>
|> Please note that this is quite different from the situation we have when
|> dealing with a pure virtual function. Because the compiler can see the '=
|> 0' syntax, it knows that it should not emit a reference to the virtual
|> function definition, and emit a call to the 'pure virtual called' handler
|> instead.
They aren't really very different. When the destructor for the base
class is running, the vtbl must point to the member functions of the
base class, not the derived classes. In the case of a pure virtual
function, the compiler must put something there. It is not difficult to
imagine an implementation which puts a pointer to the operator delete in
the vtbl as well. The only real difference, of course, is when the
implementation discovers that it needs the placeholder. In the case of
pure virtual functions, it knows it when compiling; in the case of the
destructor, it cannot know before linking.
|> I'm also puzzled by your remark about undefined destructors. In all the
|> implementations I know of, a used undefined destructor leads to a to
|> link-time error. Is there something in the draft saying that a destructor
|> which is not defined may lead to undefined run-time behaviour?
My point was that it was not really clear in the draft. See earlier
postings in this thread. The question is: what should be required?
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/05/07 Raw View
Wil Evers wrote:
>
> In all the implementations I know of, an undefined external is not just a
> warning one can decide to ignore and continue business as usual. It is a
> fatal error precluding the generation of the program.
Intel linkers will generate an executable with unresolved externals, and
return a lower error level for the warning than it does for a fatal
error. I think Borland does too, but I always let Make delete the target
anyway, so I'm not sure.
> > You're right that the standard shouldn't be ambiguous. I wouldn't object
> > if it required the operator, as long as it didn't prohibit an
> > implementation from not enforcing the requirement if the implementation
> > is able to do without the definition.
>
> I don't get this: if no portable and reasonably efficient implementation is
> possible without such a definition, then why not simply require it?
> Conversely, if a reasonable implementation is possible without the need for
> such a definition, then why bother the user by requiring one?
You're probably right. I'm just not sure which is the best choice,
choosing an efficient implementation that winds up making it necessary
to define operator delete, or insisting upon not having to define
operator delete and winding up with a slightly less efficient
implementation.
--
Ciao,
Paul
(Please send e-mail to mailto:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/05/05 Raw View
"Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com> writes:
|> Wil Evers wrote:
|> > > 3) it would be difficult to avoid this, therefore,
|> > >
|> > > 4) perhaps the standard should be amended to allow an implementation to
|> > > require operator delete in this case.
|> >
|> > I disagree. The standard should not be ambiguous about what needs to be
|> > defined.
|>
|> You're right that the standard shouldn't be ambiguous. I wouldn't object
|> if it required the operator, as long as it didn't prohibit an
|> implementation from not enforcing the requirement if the implementation
|> is able to do without the definition.
I see two alternatives that the standard could adopt: either it could
systematically require the implementation, even if it was never used,
much as it does with virtual functions, or it could simple say that
using it if it isn't defined is undefined behavior, much like calling a
pure virtual function virtually (e.g.: from within a constructor). Note
that in the latter case, most compilers will give you a run-time error
message and abort; I would expect a similar solution to be adopted in
the case of the undefined destructor.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Wil Evers" <wil@ittpub.nl>
Date: 1997/05/06 Raw View
Hi,
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote in article
<rf5d8r69vam.fsf@vx.cit.alcatel.fr>...
>
> "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com> writes:
>
> |> You're right that the standard shouldn't be ambiguous. I wouldn't
> |> object if it required the operator, as long as it didn't prohibit an
> |> implementation from not enforcing the requirement if the
implementation
> |> is able to do without the definition.
>
> I see two alternatives that the standard could adopt: either it could
> systematically require the implementation, even if it was never used,
> much as it does with virtual functions, or it could simple say that
> using it if it isn't defined is undefined behavior, much like calling a
> pure virtual function virtually (e.g.: from within a constructor). Note
> that in the latter case, most compilers will give you a run-time error
> message and abort; I would expect a similar solution to be adopted in
> the case of the undefined destructor.
Practically speaking, I don't think your second alternative is easy to
implement. The current draft requires that if a class has a virtual
destructor, the operator delete to use is found at run-time, based on the
object's most derived type. To me, this implies that a reference to that
operator delete must somehow be present in the emitted code. Therefore, I
would expect a link-time error when it is not defined, and I don't see how
such an error could be postponed until run-time without invoking some sort
of dynamic linking magic.
Please note that this is quite different from the situation we have when
dealing with a pure virtual function. Because the compiler can see the '=
0' syntax, it knows that it should not emit a reference to the virtual
function definition, and emit a call to the 'pure virtual called' handler
instead.
I'm also puzzled by your remark about undefined destructors. In all the
implementations I know of, a used undefined destructor leads to a to
link-time error. Is there something in the draft saying that a destructor
which is not defined may lead to undefined run-time behaviour?
- Wil
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/30 Raw View
Wil Evers wrote:
>
> If I write...
>
> struct B {
> virtual void f();
> virtual ~B() { }
> };
>
> struct D : B {
> void f();
> void operator delete(void *);
> };
>
> void g(B& aB) { aB.f(); }
>
> void h() { D myD; g(myD); }
>
> ...and the program contains no delete-expression deleting an object whose
> most derived type is D or derived from D, then is D's operator delete
> required to be defined?
>
> Section 3.2 [basic.def.odr] seems to imply that there is no such
> requirement: it requires every used non-inline function to be defined
> exactly once, but since the program contains no potentially evaluated
> delete-expression deleting a D, the deallocation function does not seem to
> be included in set of used functions for the program.
>
> On the other hand, because B has a virtual destructor, clause 8 of section
> 12.5 [class.free] requires D's operator delete to be called when a D is
> destroyed by doing a delete on a pointer to a B.
>
> If we assume a conventional implementation using virtual function tables,
> it looks to me as though D's vtbl must contain a pointer to a routine with
> a call to D's operator delete in it. Therefore, I would expect a linker
> error if D's operator delete is not defined.
>
> To me, it seems logical to require a class-specific operator delete to be
> defined if it that class has a virtual destructor; however, it could not
> find any such requirement in the draft.
I guess you just missed the last thread on this topic. The general
consensus seems to be that:
1) the standard doesn't require the operator delete to be defined, but:
2) many existing implementations will in fact report an unresolved
external at link time, and:
3) it would be difficult to avoid this, therefore,
4) perhaps the standard should be amended to allow an implementation to
require operator delete in this case.
--
Ciao,
Paul
(Please send e-mail to mailto:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: "Wil Evers" <wil@ittpub.nl>
Date: 1997/05/01 Raw View
Hi,
Paul D. DeRocco <strip_these_words_pderocco@ix.netcom.com> wrote in article
<3366955B.4517@ix.netcom.com>...
> Wil Evers wrote:
>
> > To me, it seems logical to require a class-specific operator delete
> > to be defined if it that class has a virtual destructor; however, it
> > could not find any such requirement in the draft.
>
> I guess you just missed the last thread on this topic.
Are you by any chance referring to the discussion *you and me* were
having on comp.lang.c++.moderated entitled 'making sure iterators
are deleted'? If you're not, then please let us know.
> The general consensus seems to be that:
Consensus? All that happened is that you and me argued a little bit :-).
> 1) the standard doesn't require the operator delete to be defined, but:
>
> 2) many existing implementations will in fact report an unresolved
> external at link time, and:
Many existing implementations gets lots of other things wrong too. That
in itself is no reason to change the standard.
> 3) it would be difficult to avoid this, therefore,
>
> 4) perhaps the standard should be amended to allow an implementation to
> require operator delete in this case.
I disagree. The standard should not be ambiguous about what needs to be
defined.
AFAIK, the current draft contains no requirement for a class-specific
operator delete to be defined, unless it is used. If that is close to
impossible to implement for a class with a virtual destructor, then for
that case the rule should change and unambiguously require such a
definition.
I posted my question to comp.std.c++ hoping someone on the committee would
explain why there is no need for such a requirement.
- Wil
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/05/02 Raw View
Wil Evers wrote:
>
> Are you by any chance referring to the discussion *you and me* were
> having on comp.lang.c++.moderated entitled 'making sure iterators
> are deleted'? If you're not, then please let us know.
I'm sorry if I forgot who was involved in the discussion, or even which
newsgroup it was in (the two blur together in my mind), but I recall
other people being involved as well.
> > 1) the standard doesn't require the operator delete to be defined, but:
> >
> > 2) many existing implementations will in fact report an unresolved
> > external at link time, and:
>
> Many existing implementations gets lots of other things wrong too. That
> in itself is no reason to change the standard.
But they report an unresolved external because they implement it in a
manner that is reasonable, but in which it would be extremely difficult
to suppress that warning. For instance, as someone (perhaps you?)
pointed out, the Borland compiler generates a reference to operator new
in _every_ constructor, and to operator delete in _every_ destructor,
even if non-virtual, since Borland chose to have a single function serve
as both constructor and allocator/constructor, and a single function as
both destructor and destructor/deallocator, based on a hidden flag
parameter passed by the compiler. This shortens the code at the call
site. However, having done this, there's no easy way (that I can see) to
suppress the unresolved external from the linker. The compiler can't
simply supply a dummy definition for operator delete when it thinks it
won't be called, because it might be called in a different module.
> > 3) it would be difficult to avoid this, therefore,
> >
> > 4) perhaps the standard should be amended to allow an implementation to
> > require operator delete in this case.
>
> I disagree. The standard should not be ambiguous about what needs to be
> defined.
You're right that the standard shouldn't be ambiguous. I wouldn't object
if it required the operator, as long as it didn't prohibit an
implementation from not enforcing the requirement if the implementation
is able to do without the definition.
--
Ciao,
Paul
(Please send e-mail to mailto:pderocco@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: "Wil Evers" <wil@ittpub.nl>
Date: 1997/04/28 Raw View
Hi,
I have a question for the standard experts.
If I write...
struct B {
virtual void f();
virtual ~B() { }
};
struct D : B {
void f();
void operator delete(void *);
};
void g(B& aB) { aB.f(); }
void h() { D myD; g(myD); }
...and the program contains no delete-expression deleting an object whose
most derived type is D or derived from D, then is D's operator delete
required to be defined?
Section 3.2 [basic.def.odr] seems to imply that there is no such
requirement: it requires every used non-inline function to be defined
exactly once, but since the program contains no potentially evaluated
delete-expression deleting a D, the deallocation function does not seem to
be included in set of used functions for the program.
On the other hand, because B has a virtual destructor, clause 8 of section
12.5 [class.free] requires D's operator delete to be called when a D is
destroyed by doing a delete on a pointer to a B.
If we assume a conventional implementation using virtual function tables,
it looks to me as though D's vtbl must contain a pointer to a routine with
a call to D's operator delete in it. Therefore, I would expect a linker
error if D's operator delete is not defined.
To me, it seems logical to require a class-specific operator delete to be
defined if it that class has a virtual destructor; however, it could not
find any such requirement in the draft.
Am I missing something?
Thanks in advance,
- Wil
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]