Submitted via IRC for TheMightyBuzzard to let us know that a serious bug in GCC.
This post is to inform you about a bug in GCC that may cause memory (or other resource) leaks in your valid C++ programs.
One of the pillars of C++ philosophy is what we often call RAII [Resource Acquisition Is Initialization]: if you use classes to manage resources, use constructors for allocating resources and destructors for releasing them, the language makes sure that whatever happens, however you use such classes the resources will get properly released.
[...] This is the contract: I take care that my classes correctly manage resources, and the language takes care that the resources will always be managed correctly regardless of the complexity of the program.
This is where the bug manifests. Member
r1
is initialized but never destroyed. Admittedly, this is a rare case: it requires an exception in the middle of initialization, a temporary and an aggregate initialization. But usually, leaks manifest in the face of exceptions. And the fact that it is rare makes you less prepared for it.Here is a full example:
#include <cstdio>
#include <stdexcept>struct Resource
{
explicit Resource(int) { std::puts("create"); }
Resource(Resource const&) { std::puts("create"); }
~Resource() { std::puts("destroy"); }
};Resource make_1() { return Resource(1); }
Resource make_2() { throw std::runtime_error("failed"); }struct User
{
Resource r1;
Resource r2;
};void process (User) {}
int main()
{
try {
process({make_1(), make_2()});
}
catch (...) {}
}You can test it online here. It is present in GCC 4, 5, and 6. For a more real-life, and somewhat longer, illustration of the problem, see this example provided by Tomasz KamiĆski.
Interesting but thankfully not my worry at the moment as I'm on a Learn Rust kick and my problem areas of SN are all perl.
Source: https://akrzemi1.wordpress.com/2017/04/27/a-serious-bug-in-gcc/
(Score: 1, Insightful) by Anonymous Coward on Tuesday May 02 2017, @01:20PM (8 children)
This is NOT a compiler bug. It's a complete misunderstand how the language works in the face of exceptions during construction. A destructor is not called for an object that is not fully and completely constructed (i.e., it's constructor throws an exception).
This is why script kiddies should use toy languages like Java, C#, Python, etc., and leave big boy languages to the professionals.
(Score: 3, Insightful) by sorokin on Tuesday May 02 2017, @02:00PM
> A destructor is not called for an object that is not fully and completely constructed (i.e., it's constructor throws an exception).
This is true. But the bug is that the destructor is not called for a completely constructed object.
Look at the example https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66139#c2 [gnu.org]
Although the object of type Test is not constructed completely, the object string Test::a is. And the desctructor for string Test::a is not called.
(Score: 1, Insightful) by Anonymous Coward on Tuesday May 02 2017, @02:08PM
That's what I was thinking. That RAII thing assumes no funky stuff happens during constructor/destructor execution. Well, funky does happen.
(Score: 0) by Anonymous Coward on Tuesday May 02 2017, @03:32PM
Big boys have better reading comprehension skills than you.
(Score: 2) by tibman on Tuesday May 02 2017, @03:45PM (1 child)
I'm sure the cobol folks once said the same thing about the C/C++ people.
SN won't survive on lurkers alone. Write comments.
(Score: 0) by Anonymous Coward on Tuesday May 02 2017, @04:13PM
They still do.
(Score: 2) by fishybell on Tuesday May 02 2017, @06:09PM (2 children)
If it makes you feel better, compiling doesn't even work with clang:
(Score: 0) by Anonymous Coward on Tuesday May 02 2017, @08:41PM
Oh yes. CLang does compile it: http://rextester.com/ZBZK69864 [rextester.com]
And works as expected.
(Score: 0) by Anonymous Coward on Wednesday May 03 2017, @03:28AM
You want "--std=c++11"
and you want to be using clang++.