hi all,
acoording to the c++ standard
"15.3.
- -10- Referring to any non-static member or base class of an object in
the handler for a function-try-block of a constructor or destructor for
that object results in undefined behavior."
it is not allowed to refer to l (delete l;) in the following code
#include <iostream>
#include <memory>
using namespace std;
struct L {
L() { cout<<"L() at "<<this<<en dl; }
~L() { cout<<"~L() at "<<this<<en dl; }
};
class X {
public:
L* l;
X() try : l(new L) {
cout<<"X() at "<<this<<en dl;
}
catch (...) { delete l; throw; }
~X(){
cout<<"~X() at "<<this<<en dl;
delete l;
}
};
int main(){
try {
X* p = new X;
delete p;
}
catch(...) { std::cout<<"som e exception occured"<<std:: endl; }
}
i wonder why this has been declared such, because it leads directly
to leaking local ressources. i know herb sutters arguments from 'more
exc. c++' (item 18) where a local pointer could refer to a meanwhile
destoyed subobject (as i understand it). but this seems to be a very
rare situation.
moreover compiled with g++ (3.3.5) the output is
L() at 0x804a018
X() at 0x804a008
~X() at 0x804a008
~L() at 0x804a018
without the leaking L
any idea ?
--
mfg
k ahrens
_______________ _______________ _______________
\ phone +49 30 2093 3113 \ :-) \
\ fax +49 30 2093 3112 \______________ ____\
\ mailto:ah****@i nformatik.hu-berlin.de \
\ http://www.informatik.hu-berlin.de/~ahrens \
\ _______________ _______________ ______________\ 6 1403
Klaus Ahrens wrote: hi all,
acoording to the c++ standard
"15.3. - -10- Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior."
it is not allowed to refer to l (delete l;) in the following code
#include <iostream> #include <memory>
using namespace std;
struct L { L() { cout<<"L() at "<<this<<en dl; } ~L() { cout<<"~L() at "<<this<<en dl; } };
class X { public: L* l; X() try : l(new L) { cout<<"X() at "<<this<<en dl; } catch (...) { delete l; throw; }
This is not legal C++. If your compiler allows such syntax (as you
imply below), it is non-conformant. ~X(){ cout<<"~X() at "<<this<<en dl; delete l; } };
int main(){ try { X* p = new X; delete p; } catch(...) { std::cout<<"som e exception occured"<<std:: endl; } }
i wonder why this has been declared such, because it leads directly to leaking local ressources. i know herb sutters arguments from 'more exc. c++' (item 18) where a local pointer could refer to a meanwhile destoyed subobject (as i understand it). but this seems to be a very rare situation.
moreover compiled with g++ (3.3.5) the output is
L() at 0x804a018 X() at 0x804a008 ~X() at 0x804a008 ~L() at 0x804a018
without the leaking L
But your code doesn't throw an exception. Try adding a second member to
X and throwing an exception in the second member's constructor:
class MyException {};
class M { M() { throw MyException(); } };
class L {};
class X
{
L* l_;
M* m_;
public:
X()
try
: l_( new L ),
m_( new M )
{}
catch( const MyException& e )
{
// Automatic rethrow of e here
}
};
Now l_ is leaked. any idea ?
Perhaps this is the same material from Herb Sutter that you're
referring to, but he says ( http://www.gotw.ca/gotw/066.htm):
"[O]nce you get into your constructor try-block's handler, any local
variables in the constructor body are also already out of scope, and
you are guaranteed that no base subobjects or member objects exist any
more, period. You can't even refer to their names. Either the parts of
your object were never constructed, or those that were constructed have
already been destroyed. So you can't be cleaning up anything that
relies on referring to a base or member of the class (and anyway,
that's what the base and member destructors are for, right?)."
In practice, that means you should use a smart pointer such as
std::auto_ptr instead of a raw pointer for all class members to prevent
leaking local resources.
The same link discusses the rationale for why C++ does things that way,
and I'll just commend it for your reading pleasure rather than recap it
here.
Cheers! --M
mlimber schrieb: Klaus Ahrens wrote:
hi all,
acoording to the c++ standard
"15.3. - -10- Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior."
it is not allowed to refer to l (delete l;) in the following code
#include <iostream> #include <memory>
using namespace std;
struct L { L() { cout<<"L() at "<<this<<en dl; } ~L() { cout<<"~L() at "<<this<<en dl; } };
class X { public: L* l; X() try : l(new L) { cout<<"X() at "<<this<<en dl; } catch (...) { delete l; throw; }
This is not legal C++. If your compiler allows such syntax (as you imply below), it is non-conformant.
~X(){ cout<<"~X() at "<<this<<en dl; delete l; } };
int main(){ try { X* p = new X; delete p; } catch(...) { std::cout<<"som e exception occured"<<std:: endl; } }
i wonder why this has been declared such, because it leads directly to leaking local ressources. i know herb sutters arguments from 'more exc. c++' (item 18) where a local pointer could refer to a meanwhile destoyed subobject (as i understand it). but this seems to be a very rare situation.
moreover compiled with g++ (3.3.5) the output is
L() at 0x804a018 X() at 0x804a008 ~X() at 0x804a008 ~L() at 0x804a018
without the leaking L
But your code doesn't throw an exception. Try adding a second member to X and throwing an exception in the second member's constructor:
class MyException {}; class M { M() { throw MyException(); } }; class L {}; class X { L* l_; M* m_; public: X() try : l_( new L ), m_( new M ) {} catch( const MyException& e ) { // Automatic rethrow of e here } };
Now l_ is leaked.
any idea ?
Perhaps this is the same material from Herb Sutter that you're referring to, but he says (http://www.gotw.ca/gotw/066.htm):
"[O]nce you get into your constructor try-block's handler, any local variables in the constructor body are also already out of scope, and you are guaranteed that no base subobjects or member objects exist any more, period. You can't even refer to their names. Either the parts of your object were never constructed, or those that were constructed have already been destroyed. So you can't be cleaning up anything that relies on referring to a base or member of the class (and anyway, that's what the base and member destructors are for, right?)."
In practice, that means you should use a smart pointer such as std::auto_ptr instead of a raw pointer for all class members to prevent leaking local resources.
The same link discusses the rationale for why C++ does things that way, and I'll just commend it for your reading pleasure rather than recap it here.
Cheers! --M
i agree with your arguments with multiple ressources, indeed i forgot to
throw, but even with an exception in my X-ctor g++ produces (obviously
wrong):
L() at 0x804b018
X() at 0x804b008
~L() at 0x804b018
some exception occured
in general c++ guarantees leak-free constructor failures by deleting
memory of half baked objects (arrays) implicitly. why couldn't this be
extended to single-ressource-owning classes at least (as in my class X)???
--
mfg
k ahrens
_______________ _______________ _______________
\ phone +49 30 2093 3113 \ :-) \
\ fax +49 30 2093 3112 \______________ ____\
\ mailto:ah****@i nformatik.hu-berlin.de \
\ http://www.informatik.hu-berlin.de/~ahrens \
\ _______________ _______________ ______________\
* Klaus Ahrens: hi all,
acoording to the c++ standard
"15.3. - -10- Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior."
it is not allowed to refer to l (delete l;) in the following code
#include <iostream> #include <memory>
using namespace std;
struct L { L() { cout<<"L() at "<<this<<en dl; } ~L() { cout<<"~L() at "<<this<<en dl; } };
class X { public: L* l; X() try : l(new L) { cout<<"X() at "<<this<<en dl; } catch (...) { delete l; throw; }
~X(){ cout<<"~X() at "<<this<<en dl; delete l; } };
int main(){ try { X* p = new X; delete p; } catch(...) { std::cout<<"som e exception occured"<<std:: endl; } }
i wonder why this has been declared such, because it leads directly to leaking local ressources.
No, the C++ rules don't.
The above program is invalid.
If you'd care to present a valid program and explain _why_ you think it
would leak, we can set you right (or perhaps it would leak, it's not
difficult to arrange for a program to leak memory).
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Klaus Ahrens wrote: mlimber schrieb: Klaus Ahrens wrote:
hi all,
acoording to the c++ standard
"15.3. - -10- Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior."
it is not allowed to refer to l (delete l;) in the following code
#include <iostream> #include <memory>
using namespace std;
struct L { L() { cout<<"L() at "<<this<<en dl; } ~L() { cout<<"~L() at "<<this<<en dl; } };
class X { public: L* l; X() try : l(new L) { cout<<"X() at "<<this<<en dl; } catch (...) { delete l; throw; }
This is not legal C++. If your compiler allows such syntax (as you imply below), it is non-conformant.
~X(){ cout<<"~X() at "<<this<<en dl; delete l; } };
int main(){ try { X* p = new X; delete p; } catch(...) { std::cout<<"som e exception occured"<<std:: endl; } }
i wonder why this has been declared such, because it leads directly to leaking local ressources. i know herb sutters arguments from 'more exc. c++' (item 18) where a local pointer could refer to a meanwhile destoyed subobject (as i understand it). but this seems to be a very rare situation.
moreover compiled with g++ (3.3.5) the output is
L() at 0x804a018 X() at 0x804a008 ~X() at 0x804a008 ~L() at 0x804a018
without the leaking L
But your code doesn't throw an exception. Try adding a second member to X and throwing an exception in the second member's constructor:
class MyException {}; class M { M() { throw MyException(); } }; class L {}; class X { L* l_; M* m_; public: X() try : l_( new L ), m_( new M ) {} catch( const MyException& e ) { // Automatic rethrow of e here } };
Now l_ is leaked.
any idea ?
Perhaps this is the same material from Herb Sutter that you're referring to, but he says (http://www.gotw.ca/gotw/066.htm):
"[O]nce you get into your constructor try-block's handler, any local variables in the constructor body are also already out of scope, and you are guaranteed that no base subobjects or member objects exist any more, period. You can't even refer to their names. Either the parts of your object were never constructed, or those that were constructed have already been destroyed. So you can't be cleaning up anything that relies on referring to a base or member of the class (and anyway, that's what the base and member destructors are for, right?)."
In practice, that means you should use a smart pointer such as std::auto_ptr instead of a raw pointer for all class members to prevent leaking local resources.
The same link discusses the rationale for why C++ does things that way, and I'll just commend it for your reading pleasure rather than recap it here.
Cheers! --M i agree with your arguments with multiple ressources, indeed i forgot to throw, but even with an exception in my X-ctor g++ produces (obviously wrong):
L() at 0x804b018 X() at 0x804b008 ~L() at 0x804b018 some exception occured
in general c++ guarantees leak-free constructor failures by deleting memory of half baked objects (arrays) implicitly. why couldn't this be extended to single-ressource-owning classes at least (as in my class X)???
All constructed members of a class *are* implicitly destroyed when the
constructor (or any function) throws an exception, and that inclues raw
pointers that happen to be members. However, the standard rules for
pointers is that if the pointer is non-null and it goes out of scope
without being deleted (or somehow passing ownership), the object it
pointed to is leaked. A simpler example:
void Foo()
{
L* rawPtr = new L;
std::auto_ptr<L > autoPtr( new L );
throw MyException();
}
In this code, rawPtr is leaked but autoPtr is not. The two key benefits
of smart pointers are that they free the programmer from having to
manually delete each new-ed object and that they provide exception
safety. Their use is not only good practice in the example with M and L
above; it is essential for a non-leaking program.
Cheers! --M
Alf P. Steinbach schrieb: * Klaus Ahrens:
hi all,
acoording to the c++ standard
"15.3. - -10- Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior."
it is not allowed to refer to l (delete l;) in the following code
#include <iostream> #include <memory>
using namespace std;
struct L { L() { cout<<"L() at "<<this<<en dl; } ~L() { cout<<"~L() at "<<this<<en dl; } };
class X { public: L* l; X() try : l(new L) { cout<<"X() at "<<this<<en dl; } catch (...) { delete l; throw; }
~X(){ cout<<"~X() at "<<this<<en dl; delete l; } };
int main(){ try { X* p = new X; delete p; } catch(...) { std::cout<<"som e exception occured"<<std:: endl; } }
i wonder why this has been declared such, because it leads directly to leaking local ressources.
No, the C++ rules don't.
The above program is invalid.
i know this for sure, and i know that auto_ptrs are much better, but my
question is concerned with the rationale behind that rule ! If you'd care to present a valid program and explain _why_ you think it would leak, we can set you right (or perhaps it would leak, it's not difficult to arrange for a program to leak memory).
* Klaus Ahrens: i know this for sure, and i know that auto_ptrs are much better, but my question is concerned with the rationale behind that rule !
Presumably you mean the rule 15.3/10 that if you refer to a non-static
member variable in a constructor's function try-block catch clause,
you're invoking Undefined Behavior
The reason is very simple: when you enter the catch clause the member
has already been destroyed, it does not exist anymore, or alternatively
it wasn't fully constructed, and did not ever come into existence; see
15.3/11.
Essentially a constructor function try-block is only useful for
converting a non-standard exception originating in the constructor's
initialization list, to a standard exception. The purpose of C++
'catch' is _not_ to do cleanup. The purpose is to fulfill contracts,
such as a constract about only throwing standard exceptions.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail? This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: vincent ngai |
last post by:
Hi folks, I have the following scenario
Lib X
A lib with 1 class and 1 template class with a static var, the ctor of the
class initialises the templated class's var.
This works if Lib X has static linkage but fubars entirely with dynamic
linkage. I'm guessing its a memory space issue
because tracing the address &foobar shows a different value when its
|
by: richardclay09 |
last post by:
The output of this:
#include <iostream>
#include <vector>
using namespace std;
struct X {
int i;
X(const X& x) : i(x.i) {
cout << "ctor copy: " << i << endl;
|
by: Levent |
last post by:
Hi,
When compiled with gcc 3.3.3 and lower on various systems (tried cygwin,
linux, aix) the following code behaves strangely:
#include <iostream>
class Foo {
public:
typedef int subs;
|
by: Chris Croughton |
last post by:
Is the following code standard-compliant, and if so what should it do?
And where in the standard defines the behaviour?
#include <stdio.h>
#define DEF defined XXX
int main(void)
{
int defined = 2;
|
by: shaun roe |
last post by:
Following up from my earlier post, where I pursued the line I outlined.
Here is the MYFunc class implementation:
MyFunc::MyFunc(int i):m_i(i){
ostringstream os;
os<<"This number is "<<m_i;
m_result = os.str();
}
| |
by: ksukhonosenko |
last post by:
This message was originally posted to comp.lang.c++.moderated
----------------------------------------------------------------------------------------------
Hi!
I face a problem in my production code. I could deduce this problem to
program shown below. It seems, that try-block in constructor doesnt
work as it should (compared to case where no try block exists at all).
I tested this small program on my MSVC .NET Pro 2003 (and separately...
|
by: Frederick Gotham |
last post by:
I have a general idea of the different kinds of behaviour described by the
C Standard, such as:
(1) Well-defined behaviour:
int a = 2, b = 3;
int c = a + b;
(Jist: The code will work perfectly.)
|
by: Grizlyk |
last post by:
Good morning.
Look here:
http://groups.google.com/group/fido7.ru.cpp.chainik/browse_frm/thread/7341aba5238c0f79
and here:
http://groups.google.com/group/fido7.ru.cpp.chainik/browse_frm/thread/cb014f4ba9df614a
Can anybody answer?
Who can't read in russian:
|
by: Sheth Raxit |
last post by:
Machine 1 :
bash-3.00$ uname -a
SunOS <hostname5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R
bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)
|
by: subramanian100in |
last post by:
consider the following program:
#include <iostream>
using namespace std;
class Test
{
public:
Test(int xx) : x(xx) { cout << x << endl; }
|
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...
| |
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,...
|
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
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,...
|
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...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
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...
| |
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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...
| |