Explicit call to destructor
up vote
17
down vote
favorite
I stumbled upon the following code snippet:
#include <iostream>
#include <string>
using namespace std;
class First
{
string *s;
public:
First() { s = new string("Text");}
~First() { delete s;}
void Print(){ cout<<*s;}
};
int main()
{
First FirstObject;
FirstObject.Print();
FirstObject.~First();
}
The text said that this snippet should cause a runtime error. Now, I wasn't really sure about that, so I tried to compile and run it. It worked. The weird thing is, despite the simplicity of the data involved, the program stuttered after printing "Text" and only after one second it completed.
I added a string to be printed to the destructor as I was unsure if it was legal to explicitly call a destructor like that. The program printed twice the string. So my guess was that the destructor is called twice as the normal program termination is unaware of the explicit call and tries to destroy the object again.
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour. So I was lucky with my compiler (VS 2017) or this specific program.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
c++ oop destructor undefined-behavior lifetime
|
show 5 more comments
up vote
17
down vote
favorite
I stumbled upon the following code snippet:
#include <iostream>
#include <string>
using namespace std;
class First
{
string *s;
public:
First() { s = new string("Text");}
~First() { delete s;}
void Print(){ cout<<*s;}
};
int main()
{
First FirstObject;
FirstObject.Print();
FirstObject.~First();
}
The text said that this snippet should cause a runtime error. Now, I wasn't really sure about that, so I tried to compile and run it. It worked. The weird thing is, despite the simplicity of the data involved, the program stuttered after printing "Text" and only after one second it completed.
I added a string to be printed to the destructor as I was unsure if it was legal to explicitly call a destructor like that. The program printed twice the string. So my guess was that the destructor is called twice as the normal program termination is unaware of the explicit call and tries to destroy the object again.
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour. So I was lucky with my compiler (VS 2017) or this specific program.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
c++ oop destructor undefined-behavior lifetime
17
The C++ standard never guarantess a runtime error (it's always undefined behavior), so the text was definitely wrong
– UnholySheep
yesterday
2
@UnholySheep, I don't know that I'd say that. For example, an exception leaving anoexcept
function is a guaranteed call tostd::terminate
, which I'd classify as a runtime error.
– chris
yesterday
@chris good point, I was only thinking about the described case (and I've seen way too many texts claim that code that invokes UB will always cause a runtime error/segmentation fault)
– UnholySheep
yesterday
How does it print the string twice? It will deallocate it twice, because the destructor will be called when the object is destroyed.
– Matthieu Brucher
yesterday
1
The runtime error definitely occurs: the destructor is called twice, it's an error and it happens at runtime. I bet you can "catch" it if you run your test in debug mode. Why is no message popping? What does VC2017 do in release mode when terminating your app knowing that the last two things it does are deleting the same pointer? Is there some optimization that hides/fixes your error by mistake? You should probably ask MS support...
– L.C.
yesterday
|
show 5 more comments
up vote
17
down vote
favorite
up vote
17
down vote
favorite
I stumbled upon the following code snippet:
#include <iostream>
#include <string>
using namespace std;
class First
{
string *s;
public:
First() { s = new string("Text");}
~First() { delete s;}
void Print(){ cout<<*s;}
};
int main()
{
First FirstObject;
FirstObject.Print();
FirstObject.~First();
}
The text said that this snippet should cause a runtime error. Now, I wasn't really sure about that, so I tried to compile and run it. It worked. The weird thing is, despite the simplicity of the data involved, the program stuttered after printing "Text" and only after one second it completed.
I added a string to be printed to the destructor as I was unsure if it was legal to explicitly call a destructor like that. The program printed twice the string. So my guess was that the destructor is called twice as the normal program termination is unaware of the explicit call and tries to destroy the object again.
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour. So I was lucky with my compiler (VS 2017) or this specific program.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
c++ oop destructor undefined-behavior lifetime
I stumbled upon the following code snippet:
#include <iostream>
#include <string>
using namespace std;
class First
{
string *s;
public:
First() { s = new string("Text");}
~First() { delete s;}
void Print(){ cout<<*s;}
};
int main()
{
First FirstObject;
FirstObject.Print();
FirstObject.~First();
}
The text said that this snippet should cause a runtime error. Now, I wasn't really sure about that, so I tried to compile and run it. It worked. The weird thing is, despite the simplicity of the data involved, the program stuttered after printing "Text" and only after one second it completed.
I added a string to be printed to the destructor as I was unsure if it was legal to explicitly call a destructor like that. The program printed twice the string. So my guess was that the destructor is called twice as the normal program termination is unaware of the explicit call and tries to destroy the object again.
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour. So I was lucky with my compiler (VS 2017) or this specific program.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
c++ oop destructor undefined-behavior lifetime
c++ oop destructor undefined-behavior lifetime
edited yesterday
gsamaras
47.4k2393173
47.4k2393173
asked yesterday
Andrea Bocco
40012
40012
17
The C++ standard never guarantess a runtime error (it's always undefined behavior), so the text was definitely wrong
– UnholySheep
yesterday
2
@UnholySheep, I don't know that I'd say that. For example, an exception leaving anoexcept
function is a guaranteed call tostd::terminate
, which I'd classify as a runtime error.
– chris
yesterday
@chris good point, I was only thinking about the described case (and I've seen way too many texts claim that code that invokes UB will always cause a runtime error/segmentation fault)
– UnholySheep
yesterday
How does it print the string twice? It will deallocate it twice, because the destructor will be called when the object is destroyed.
– Matthieu Brucher
yesterday
1
The runtime error definitely occurs: the destructor is called twice, it's an error and it happens at runtime. I bet you can "catch" it if you run your test in debug mode. Why is no message popping? What does VC2017 do in release mode when terminating your app knowing that the last two things it does are deleting the same pointer? Is there some optimization that hides/fixes your error by mistake? You should probably ask MS support...
– L.C.
yesterday
|
show 5 more comments
17
The C++ standard never guarantess a runtime error (it's always undefined behavior), so the text was definitely wrong
– UnholySheep
yesterday
2
@UnholySheep, I don't know that I'd say that. For example, an exception leaving anoexcept
function is a guaranteed call tostd::terminate
, which I'd classify as a runtime error.
– chris
yesterday
@chris good point, I was only thinking about the described case (and I've seen way too many texts claim that code that invokes UB will always cause a runtime error/segmentation fault)
– UnholySheep
yesterday
How does it print the string twice? It will deallocate it twice, because the destructor will be called when the object is destroyed.
– Matthieu Brucher
yesterday
1
The runtime error definitely occurs: the destructor is called twice, it's an error and it happens at runtime. I bet you can "catch" it if you run your test in debug mode. Why is no message popping? What does VC2017 do in release mode when terminating your app knowing that the last two things it does are deleting the same pointer? Is there some optimization that hides/fixes your error by mistake? You should probably ask MS support...
– L.C.
yesterday
17
17
The C++ standard never guarantess a runtime error (it's always undefined behavior), so the text was definitely wrong
– UnholySheep
yesterday
The C++ standard never guarantess a runtime error (it's always undefined behavior), so the text was definitely wrong
– UnholySheep
yesterday
2
2
@UnholySheep, I don't know that I'd say that. For example, an exception leaving a
noexcept
function is a guaranteed call to std::terminate
, which I'd classify as a runtime error.– chris
yesterday
@UnholySheep, I don't know that I'd say that. For example, an exception leaving a
noexcept
function is a guaranteed call to std::terminate
, which I'd classify as a runtime error.– chris
yesterday
@chris good point, I was only thinking about the described case (and I've seen way too many texts claim that code that invokes UB will always cause a runtime error/segmentation fault)
– UnholySheep
yesterday
@chris good point, I was only thinking about the described case (and I've seen way too many texts claim that code that invokes UB will always cause a runtime error/segmentation fault)
– UnholySheep
yesterday
How does it print the string twice? It will deallocate it twice, because the destructor will be called when the object is destroyed.
– Matthieu Brucher
yesterday
How does it print the string twice? It will deallocate it twice, because the destructor will be called when the object is destroyed.
– Matthieu Brucher
yesterday
1
1
The runtime error definitely occurs: the destructor is called twice, it's an error and it happens at runtime. I bet you can "catch" it if you run your test in debug mode. Why is no message popping? What does VC2017 do in release mode when terminating your app knowing that the last two things it does are deleting the same pointer? Is there some optimization that hides/fixes your error by mistake? You should probably ask MS support...
– L.C.
yesterday
The runtime error definitely occurs: the destructor is called twice, it's an error and it happens at runtime. I bet you can "catch" it if you run your test in debug mode. Why is no message popping? What does VC2017 do in release mode when terminating your app knowing that the last two things it does are deleting the same pointer? Is there some optimization that hides/fixes your error by mistake? You should probably ask MS support...
– L.C.
yesterday
|
show 5 more comments
3 Answers
3
active
oldest
votes
up vote
29
down vote
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour.
That is true. Undefined Behavor is invoked if you explicitly destroy an object with automatic storage. Learn more about it.
So I was lucky with my compiler (VS 2017) or this specific program.
I'd say you were unlucky. The best (for you, the coder) that can happen with UB is a crash at first run. If it appears to work fine, the crash could happen in January 19, 2038 in production.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
Yes, the text's kinda wrong. Undefined behavior is undefined. A run-time error is only one of many possibilities (including nasal demons).
A good read about undefined behavor: What is undefined behavor?
5
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
3
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
add a comment |
up vote
14
down vote
No this is simply undefined behavior from the draft C++ standard [class.dtor]p16:
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life]).
[ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
— end example
and we can see from the defintion of undefined behavior:
behavior for which this document imposes no requirements
You can have no expectations as to the results. It may have behaved that way for the author on their specific compiler with specific options on a specific machine but we can't expect it to be a portable nor reliable result. Althought there are cases where the implementation does try to obtain a specific result but that is just another form of acceptable undefined behavior.
Additionally [class.dtor]p15 gives more context on the normative section I quote above:
[ Note: Explicit calls of destructors are rarely needed.
One use of such calls is for objects placed at specific addresses using a placement new-expression.
Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
For example,
void* operator new(std::size_t, void* p) { return p; }
struct X {
X(int);
~X();
};
void f(X* p);
void g() { // rare, specialized use:
char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf and initialize
f(p);
p->X::~X(); // cleanup
}
— end note ]
add a comment |
up vote
7
down vote
Is the text simply wrong about the runtime error?
It is wrong.
Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
You cannot know, and this is what happens when your code invokes Undefined Behavior; you don't know what will happen when you execute it.
In your case, you were (un)lucky* and it worked, while for me, it caused an error (double free).
*Because if you received an error you would start debugging, otherwise, in a large project for example, you might missed it...
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
29
down vote
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour.
That is true. Undefined Behavor is invoked if you explicitly destroy an object with automatic storage. Learn more about it.
So I was lucky with my compiler (VS 2017) or this specific program.
I'd say you were unlucky. The best (for you, the coder) that can happen with UB is a crash at first run. If it appears to work fine, the crash could happen in January 19, 2038 in production.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
Yes, the text's kinda wrong. Undefined behavior is undefined. A run-time error is only one of many possibilities (including nasal demons).
A good read about undefined behavor: What is undefined behavor?
5
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
3
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
add a comment |
up vote
29
down vote
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour.
That is true. Undefined Behavor is invoked if you explicitly destroy an object with automatic storage. Learn more about it.
So I was lucky with my compiler (VS 2017) or this specific program.
I'd say you were unlucky. The best (for you, the coder) that can happen with UB is a crash at first run. If it appears to work fine, the crash could happen in January 19, 2038 in production.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
Yes, the text's kinda wrong. Undefined behavior is undefined. A run-time error is only one of many possibilities (including nasal demons).
A good read about undefined behavor: What is undefined behavor?
5
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
3
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
add a comment |
up vote
29
down vote
up vote
29
down vote
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour.
That is true. Undefined Behavor is invoked if you explicitly destroy an object with automatic storage. Learn more about it.
So I was lucky with my compiler (VS 2017) or this specific program.
I'd say you were unlucky. The best (for you, the coder) that can happen with UB is a crash at first run. If it appears to work fine, the crash could happen in January 19, 2038 in production.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
Yes, the text's kinda wrong. Undefined behavior is undefined. A run-time error is only one of many possibilities (including nasal demons).
A good read about undefined behavor: What is undefined behavor?
A simple search confirmed that explicitly calling a destructor on an automated object is dangerous, as the second call (when the object goes out of scope) has undefined behaviour.
That is true. Undefined Behavor is invoked if you explicitly destroy an object with automatic storage. Learn more about it.
So I was lucky with my compiler (VS 2017) or this specific program.
I'd say you were unlucky. The best (for you, the coder) that can happen with UB is a crash at first run. If it appears to work fine, the crash could happen in January 19, 2038 in production.
Is the text simply wrong about the runtime error? Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
Yes, the text's kinda wrong. Undefined behavior is undefined. A run-time error is only one of many possibilities (including nasal demons).
A good read about undefined behavor: What is undefined behavor?
edited yesterday
answered yesterday
YSC
18.9k34589
18.9k34589
5
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
3
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
add a comment |
5
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
3
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
5
5
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
"Undefined Behavor is invoked when you explicitly destroy an object with automatic storage" - More like it's invoked when the object reaches the end of its natural lifetime without being reincarnated. The destructor call itself is not UB per se.
– StoryTeller
yesterday
3
3
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
More precisely, 03:14:08 UTC on 19 January 2038 :D
– George Spatacean
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
@StoryTeller That's true. I wanted to avoid specifics. I've fixed it.
– YSC
yesterday
add a comment |
up vote
14
down vote
No this is simply undefined behavior from the draft C++ standard [class.dtor]p16:
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life]).
[ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
— end example
and we can see from the defintion of undefined behavior:
behavior for which this document imposes no requirements
You can have no expectations as to the results. It may have behaved that way for the author on their specific compiler with specific options on a specific machine but we can't expect it to be a portable nor reliable result. Althought there are cases where the implementation does try to obtain a specific result but that is just another form of acceptable undefined behavior.
Additionally [class.dtor]p15 gives more context on the normative section I quote above:
[ Note: Explicit calls of destructors are rarely needed.
One use of such calls is for objects placed at specific addresses using a placement new-expression.
Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
For example,
void* operator new(std::size_t, void* p) { return p; }
struct X {
X(int);
~X();
};
void f(X* p);
void g() { // rare, specialized use:
char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf and initialize
f(p);
p->X::~X(); // cleanup
}
— end note ]
add a comment |
up vote
14
down vote
No this is simply undefined behavior from the draft C++ standard [class.dtor]p16:
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life]).
[ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
— end example
and we can see from the defintion of undefined behavior:
behavior for which this document imposes no requirements
You can have no expectations as to the results. It may have behaved that way for the author on their specific compiler with specific options on a specific machine but we can't expect it to be a portable nor reliable result. Althought there are cases where the implementation does try to obtain a specific result but that is just another form of acceptable undefined behavior.
Additionally [class.dtor]p15 gives more context on the normative section I quote above:
[ Note: Explicit calls of destructors are rarely needed.
One use of such calls is for objects placed at specific addresses using a placement new-expression.
Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
For example,
void* operator new(std::size_t, void* p) { return p; }
struct X {
X(int);
~X();
};
void f(X* p);
void g() { // rare, specialized use:
char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf and initialize
f(p);
p->X::~X(); // cleanup
}
— end note ]
add a comment |
up vote
14
down vote
up vote
14
down vote
No this is simply undefined behavior from the draft C++ standard [class.dtor]p16:
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life]).
[ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
— end example
and we can see from the defintion of undefined behavior:
behavior for which this document imposes no requirements
You can have no expectations as to the results. It may have behaved that way for the author on their specific compiler with specific options on a specific machine but we can't expect it to be a portable nor reliable result. Althought there are cases where the implementation does try to obtain a specific result but that is just another form of acceptable undefined behavior.
Additionally [class.dtor]p15 gives more context on the normative section I quote above:
[ Note: Explicit calls of destructors are rarely needed.
One use of such calls is for objects placed at specific addresses using a placement new-expression.
Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
For example,
void* operator new(std::size_t, void* p) { return p; }
struct X {
X(int);
~X();
};
void f(X* p);
void g() { // rare, specialized use:
char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf and initialize
f(p);
p->X::~X(); // cleanup
}
— end note ]
No this is simply undefined behavior from the draft C++ standard [class.dtor]p16:
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life]).
[ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
— end example
and we can see from the defintion of undefined behavior:
behavior for which this document imposes no requirements
You can have no expectations as to the results. It may have behaved that way for the author on their specific compiler with specific options on a specific machine but we can't expect it to be a portable nor reliable result. Althought there are cases where the implementation does try to obtain a specific result but that is just another form of acceptable undefined behavior.
Additionally [class.dtor]p15 gives more context on the normative section I quote above:
[ Note: Explicit calls of destructors are rarely needed.
One use of such calls is for objects placed at specific addresses using a placement new-expression.
Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
For example,
void* operator new(std::size_t, void* p) { return p; }
struct X {
X(int);
~X();
};
void f(X* p);
void g() { // rare, specialized use:
char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf and initialize
f(p);
p->X::~X(); // cleanup
}
— end note ]
edited yesterday
answered yesterday
Shafik Yaghmour
122k23305509
122k23305509
add a comment |
add a comment |
up vote
7
down vote
Is the text simply wrong about the runtime error?
It is wrong.
Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
You cannot know, and this is what happens when your code invokes Undefined Behavior; you don't know what will happen when you execute it.
In your case, you were (un)lucky* and it worked, while for me, it caused an error (double free).
*Because if you received an error you would start debugging, otherwise, in a large project for example, you might missed it...
add a comment |
up vote
7
down vote
Is the text simply wrong about the runtime error?
It is wrong.
Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
You cannot know, and this is what happens when your code invokes Undefined Behavior; you don't know what will happen when you execute it.
In your case, you were (un)lucky* and it worked, while for me, it caused an error (double free).
*Because if you received an error you would start debugging, otherwise, in a large project for example, you might missed it...
add a comment |
up vote
7
down vote
up vote
7
down vote
Is the text simply wrong about the runtime error?
It is wrong.
Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
You cannot know, and this is what happens when your code invokes Undefined Behavior; you don't know what will happen when you execute it.
In your case, you were (un)lucky* and it worked, while for me, it caused an error (double free).
*Because if you received an error you would start debugging, otherwise, in a large project for example, you might missed it...
Is the text simply wrong about the runtime error?
It is wrong.
Or is it really common to have runtime error? Or maybe my compiler implemented some kind of warding mechanism against this kind of things?
You cannot know, and this is what happens when your code invokes Undefined Behavior; you don't know what will happen when you execute it.
In your case, you were (un)lucky* and it worked, while for me, it caused an error (double free).
*Because if you received an error you would start debugging, otherwise, in a large project for example, you might missed it...
answered yesterday
gsamaras
47.4k2393173
47.4k2393173
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262269%2fexplicit-call-to-destructor%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
17
The C++ standard never guarantess a runtime error (it's always undefined behavior), so the text was definitely wrong
– UnholySheep
yesterday
2
@UnholySheep, I don't know that I'd say that. For example, an exception leaving a
noexcept
function is a guaranteed call tostd::terminate
, which I'd classify as a runtime error.– chris
yesterday
@chris good point, I was only thinking about the described case (and I've seen way too many texts claim that code that invokes UB will always cause a runtime error/segmentation fault)
– UnholySheep
yesterday
How does it print the string twice? It will deallocate it twice, because the destructor will be called when the object is destroyed.
– Matthieu Brucher
yesterday
1
The runtime error definitely occurs: the destructor is called twice, it's an error and it happens at runtime. I bet you can "catch" it if you run your test in debug mode. Why is no message popping? What does VC2017 do in release mode when terminating your app knowing that the last two things it does are deleting the same pointer? Is there some optimization that hides/fixes your error by mistake? You should probably ask MS support...
– L.C.
yesterday