473,785 Members | 2,916 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

gcc, class forward declarations and destructor calls

I once made my own smart pointer implementation for a project and
at one point fought to death to find a malicious bug. The program
was not working and I couldn't figure out why.
The source of the problem was that MSVC++ was not giving me a
warning even though it should have. The problem was that I was
creating a smart pointer from a forward-declaration of a class
which, it seems, makes it impossible for the smart pointer to call
the destructor of the class properly.
In other words, I had something like this:

class SomeClass;

class AnotherClass
{
SmartPtr<SomeCl assptr;
...
};

After including the full declaration of SomeClass instead of just
forward-declaring it, it started working.

Now, I decided to try what gcc says about this. When I did, it was
way more informative. It said, among other things:

SmartPtr.hh:80: warning: possible problem detected in invocation
of delete operator:
SmartPtr.hh:80: note: neither the destructor nor the class-specific
operator delete will be called, even if they are declared when the
class is defined.

Ok, I can buy that. I assume this agrees with the C++ standard?

However, now comes the weird stuff: If I compile a test program
with gcc with either no optimizations or just with "-O" then it
indeed does not call the destructor of that class. However, if
I compile with "-O2" or higher, it *does* call the destructor!
(It still gives the warning, though.)

I even tried making SomeClass be derived from a base class with
a virtual destructor, and both destructors were properly called
when compiling with "-O2" (but none when compiling with "-O" or
without it).

I'm curious: Why?
Mar 5 '07 #1
3 3859
On Mon, 05 Mar 2007 14:37:55 +0200, Juha Nieminen wrote:
I once made my own smart pointer implementation for a project and
at one point fought to death to find a malicious bug. The program
was not working and I couldn't figure out why.
The source of the problem was that MSVC++ was not giving me a
warning even though it should have. The problem was that I was
creating a smart pointer from a forward-declaration of a class
which, it seems, makes it impossible for the smart pointer to call
the destructor of the class properly.
In other words, I had something like this:

class SomeClass;

class AnotherClass
{
SmartPtr<SomeCl assptr;
...
};

After including the full declaration of SomeClass instead of just
forward-declaring it, it started working.

Now, I decided to try what gcc says about this. When I did, it was
way more informative. It said, among other things:

SmartPtr.hh:80: warning: possible problem detected in invocation
of delete operator:
SmartPtr.hh:80: note: neither the destructor nor the class-specific
operator delete will be called, even if they are declared when the
class is defined.

Ok, I can buy that. I assume this agrees with the C++ standard?

However, now comes the weird stuff: If I compile a test program
with gcc with either no optimizations or just with "-O" then it
indeed does not call the destructor of that class. However, if
I compile with "-O2" or higher, it *does* call the destructor!
(It still gives the warning, though.)
Sounds like you are invoking Undefined Behaviour - in which case all bets
are off and the compiler can do whatever it likes (including defrosting
your fridge). So not so much "weird", perhaps, as "irrelevant ".
I even tried making SomeClass be derived from a base class with
a virtual destructor, and both destructors were properly called when
compiling with "-O2" (but none when compiling with "-O" or without it).

I'm curious: Why?
Who cares? It's UB. My guess might be that something gets inlined
somewhere or perhaps the order of some function calls is different between
the two cases.

--
Lionel B
Mar 5 '07 #2
JLS
On Mar 5, 8:08 am, Lionel B <m...@privacy.n etwrote:
On Mon, 05 Mar 2007 14:37:55 +0200, Juha Nieminen wrote:
I once made my own smart pointer implementation for a project and
at one point fought to death to find a malicious bug. The program
was not working and I couldn't figure out why.
The source of the problem was that MSVC++ was not giving me a
warning even though it should have. The problem was that I was
creating a smart pointer from a forward-declaration of a class
which, it seems, makes it impossible for the smart pointer to call
the destructor of the class properly.
In other words, I had something like this:
class SomeClass;
class AnotherClass
{
SmartPtr<SomeCl assptr;
...
};
After including the full declaration of SomeClass instead of just
forward-declaring it, it started working.
Now, I decided to try what gcc says about this. When I did, it was
way more informative. It said, among other things:
SmartPtr.hh:80: warning: possible problem detected in invocation
of delete operator:
SmartPtr.hh:80: note: neither the destructor nor the class-specific
operator delete will be called, even if they are declared when the
class is defined.
Ok, I can buy that. I assume this agrees with the C++ standard?
However, now comes the weird stuff: If I compile a test program
with gcc with either no optimizations or just with "-O" then it
indeed does not call the destructor of that class. However, if
I compile with "-O2" or higher, it *does* call the destructor!
(It still gives the warning, though.)

Sounds like you are invoking Undefined Behaviour - in which case all bets
are off and the compiler can do whatever it likes (including defrosting
your fridge). So not so much "weird", perhaps, as "irrelevant ".
I even tried making SomeClass be derived from a base class with
a virtual destructor, and both destructors were properly called when
compiling with "-O2" (but none when compiling with "-O" or without it).
I'm curious: Why?

Who cares? It's UB. My guess might be that something gets inlined
somewhere or perhaps the order of some function calls is different between
the two cases.

--
Lionel B- Hide quoted text -

- Show quoted text -
It may be undefined behavior, but that doesn't mean that someone
cannot be curious as to what the compiler is doing. As such, it seems
like a reasonable question, even if others do not care. It seems to
me, however, that as this question is a compiler specific question, it
would be better asked in a forum geared to that particular compiler.

I would think that a better understanding of the operations of a
particular compiler would allow users of that compiler to better
understand issues which they may, or may not have, with that compiler.
Knowing what error cases a compiler will catch and report, and which
ones will be ignored, is of obvious use, if you use that compiler. It
may be undefined behavior, but a good compiler will catch and report
that. We are long past the stage where "garbage in - garbage out" was
acceptable to anyone but a newbie. The purpose of a compiler is to
make it easier for a developer to accomplish a given task. Defrosting
your fridge may be acceptable by the language definition, but it is
not acceptable for the implementation of the language. Generating a
warning, is.

MSVC++ has several warning levels as well as an option to catch
warnings that are only detectable when optimization is turned on. I
would make sure that the warning levels are at 4 and the other option
turned on. There is also some value is running programs through static
code analyzers such as PC-Lint, Fortify, Coverity, among others. You
will find errors in your program. This may be one of them.

Mar 5 '07 #3
On Mon, 05 Mar 2007 07:04:40 -0800, JLS wrote:
On Mar 5, 8:08 am, Lionel B <m...@privacy.n etwrote:
>On Mon, 05 Mar 2007 14:37:55 +0200, Juha Nieminen wrote:
I once made my own smart pointer implementation for a project and
at one point fought to death to find a malicious bug. The program
was not working and I couldn't figure out why.
[snip]
However, now comes the weird stuff: If I compile a test program
with gcc with either no optimizations or just with "-O" then it
indeed does not call the destructor of that class. However, if
I compile with "-O2" or higher, it *does* call the destructor!
(It still gives the warning, though.)

Sounds like you are invoking Undefined Behaviour - in which case all bets
are off and the compiler can do whatever it likes (including defrosting
your fridge). So not so much "weird", perhaps, as "irrelevant ".
I even tried making SomeClass be derived from a base class with
a virtual destructor, and both destructors were properly called when
compiling with "-O2" (but none when compiling with "-O" or without it).
I'm curious: Why?

Who cares? It's UB. My guess might be that something gets inlined
somewhere or perhaps the order of some function calls is different between
the two cases.

--
Lionel B
Please don't quote sigs.
>- Hide quoted text -
- Show quoted text -
or this stuff.
It may be undefined behavior, but that doesn't mean that someone
cannot be curious as to what the compiler is doing. As such, it seems
like a reasonable question, even if others do not care. It seems to
me, however, that as this question is a compiler specific question, it
would be better asked in a forum geared to that particular compiler.
Definitely. The OP's query was technically OT. Your commentary on the
other hand is, to my mind, borderline on-topic ;)
I would think that a better understanding of the operations of a
particular compiler would allow users of that compiler to better
understand issues which they may, or may not have, with that compiler.
Knowing what error cases a compiler will catch and report, and which
ones will be ignored, is of obvious use, if you use that compiler. It
may be undefined behavior, but a good compiler will catch and report
that.
As did one of the OP's compilers...
We are long past the stage where "garbage in - garbage out" was
acceptable to anyone but a newbie. The purpose of a compiler is to
make it easier for a developer to accomplish a given task. Defrosting
your fridge may be acceptable by the language definition, but it is
not acceptable for the implementation of the language. Generating a
warning, is.
Agreed. However in practice, since a compiler cannot possibly report every
instance of potentially UB, I believe it is actually dangerous to rely on
your compiler to detect badly-written or semantically incorrect code (and
bad form to whinge about it when your compiler fails to nanny you to
your satisfaction).
MSVC++ has several warning levels as well as an option to catch
warnings that are only detectable when optimization is turned on. I
would make sure that the warning levels are at 4 and the other option
turned on. There is also some value is running programs through static
code analyzers such as PC-Lint, Fortify, Coverity, among others. You
will find errors in your program. This may be one of them.
Sure, I always have my warning level turned up to 11 (and if possible set
my compiler to treat warnings as errors). But bugs still get through and
even if it makes me feel better I cannot in all honesty blame the
compiler for not spotting my own cruddy coding errors.

--
Lionel B
Mar 5 '07 #4

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

Similar topics

10
8184
by: Angus Leeming | last post by:
Hello, Could someone explain to me why the Standard conveners chose to typedef std::string rather than derive it from std::basic_string<char, ...>? The result of course is that it is effectively impossible to forward declare std::string. (Yes I am aware that some libraries have a string_fwd.h header, but this is not portable.) That said, is there any real reason why I can't derive an otherwise empty
15
2783
by: Mon | last post by:
I am in the process of reorganizing my code and came across and I came across a problem, as described in the subject line of this posting. I have many classes that have instances of other classes as member variables. So including a forward declaration doesnt help, does it? Faced with these, I had the following options: -Include the appropriate header in the header file that contains the class definition that has a member variable that is...
28
2023
by: Steven T. Hatton | last post by:
I will assume many people reading this would never create anything similar to the example below. So let me preface this with _*IF*_ you were in a situation where you had to chose between using #includes or forward declaring each class in diamond.h, which would you choose? Why? If there is something fundamentally wrong with the way I've approached the structure of this example, I am interested to know. As for preferences and tastes, I...
23
5184
by: Fabian Müller | last post by:
Hi all, my question is as follows: If have a class X and a class Y derived from X. Constructor of X is X(param1, param2) . Constructor of Y is Y(param1, ..., param4) .
0
1363
by: Leslaw Bieniasz | last post by:
Cracow, 16.09.2004 Hi, I have a problem with compiling the following construction involving cross-calls of class template methods, with additional inheritance. I want to have three class templates: ------------------------------------------ in file "Model.h":
23
3861
by: mark.moore | last post by:
I know this has been asked before, but I just can't find the answer in the sea of hits... How do you forward declare a class that is *not* paramaterized, but is based on a template class? Here's what I thought should work, but apparently doesn't: class Foo; void f1(Foo* p)
3
1697
by: cpisz | last post by:
I have seen this on the top of a few header files class SomeClass; What does it mean? I would expect some sort of declaration or defintion following such as class SomeClass {
9
5507
by: silversurfer2025 | last post by:
Hello everyone, I am currently having problems with a C++ abstract class. I have a class FrameWork.h which defines some methods (of which some are abstract, i.e. virtual void method() = 0). In FrameWork.cpp I define some of the methods while I naturally leave the abstract methods undefined. Now I wrote a class FrameWork_GUI.h which inherits from the abstract FrameWork class and implements the missing (so far abstract) methods....
10
3516
by: =?Utf-8?B?TWF4IDFlNg==?= | last post by:
I have an application form named Form1.h. The code for this form is a namespace (MyNamespace) with two classes in it (Form1 and MyClass). Form1 has windows designer code and some button event handlers. In those event handlers I want to reference methods in the MyClass class. I use syntax like this: double F = MyClass::MyMethod(x,y); As soon as I type the second colon I get a full list of all the exposed methods in MyClass and I sense I...
0
9645
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9480
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10093
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9952
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7500
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5381
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4053
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 we have to send another system
3
2880
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 can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.