Exception in aggregate initialization - c++

In C++14 (gcc 6.3) I have the following code:
#include <memory>
#include <vector>
#include <stdexcept>
struct A
{
int a1;
int a2;
};
struct B
{
int b1;
std::shared_ptr< std::vector<A> > Alist;
};
struct C
{
std::shared_ptr<B> b;
std::shared_ptr< std::vector<A> > Alist;
};
std::shared_ptr< std::vector<A> > makeListA()
{
std::vector<A> toto = {{0,1}, {2,3}};
return std::make_shared< std::vector<A> >(toto);
}
std::shared_ptr< std::vector<A> > makeListAWithException()
{
throw std::out_of_range("My exception");
}
std::shared_ptr<B> makeB()
{
return std::make_shared<B>(B{0, makeListA()});
}
main()
{
std::make_unique<C>(C{makeB(),makeListAWithException()});
}
When running valgrind i have a memory leak : it looks like the objects created by "makeB()" function were not freed. I had this problem only when using aggregate initialization with curly braces.
When I define an explicit constructor on each class (A, B and C), I don't have this issue.
What am I doing wrong ?
Best regards

This is gcc bug 66139. Here is a short reproduction, courtesy of Andrzej (with a more thorough description available in the blog post):
#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 (...) {}
}
This prints:
create
It should print (as clang, correctly, does):
create
destroy

You don't have associated try/catch so your program terminate.
stack unwinding is not required in that case.
Following should solve your possible leak.
int main()
{
try
{
std::make_unique<C>(C{makeB(), makeListAWithException()});
}
catch (...)
{
}
}

if you change to like below, i think the problem is fixed
std::make_unique<C>(C{makeB(),makeListAWithException()});
to
auto b = makeB();
std::make_unique<C>(C{b,makeListAWithException()});

Related

Relaunch an exception in a constructor later instruction delete this

I have following code,
my_class.cpp
#include "my_class.h"
my_class::my_class(int m)
{
try
{
my_method();
throw My_Exception();
}
catch(exception &e)
{
delete this;
throw;
}
}
my_class::~my_class()
{
for(auto &el : my_member)
if(el!=NULL)
delete el;
}
void my_class::my_method()
{
for(int i ; i<5 ; i++)
my_member.push_back(new dfa(i)); //dfa is another class
}
my_class.h
#include "dfa.h"
#include "exception.h"
using namespace std;
class my_class
{
public :
my_class();
~my_class();
void my_method();
private :
vector<dfa *> my_member;
};
exception.h
#include <exception>
class My_Exception : public exception
{
public:
const char * what () const throw ()
{
return "Generic Exception";
}
};
main.cpp
#include <iostream>
#include "my_class.h"
int main()
{
try
{
my_class *ptr = new my_class(3);
}
catch(exception &e)
{
cout<<e.what()<<endl;
}
}
the class dfa is missing, but is a normal class. The problem is in the catch, when i do delete this the denstructor is invoked and dynamics objects of class dfa deallocated but the exception isn't relaunched. The execution flow doesn't return to main (in the catch block of the main) because there is a segmentation fault. What could be the problem?
(I can't use shared or auto ptr to handle memory because I'm using a big library)
(I'm using C++11)
delete does a lot more work than just calling the destructor.
You cannot call delete on an incomplete object, which is the case since the constructor never completed successfully.
The implication is that when handling exceptions in a constructor, you need to do the cleanup yourself, but you cannot simply call delete, as this will conflict with the way new deals with exceptions.
Here's a way to fix this:
my_class::my_class(int m)
{
try
{
my_method();
throw My_Exception();
}
catch(exception &e)
{
cleanup();
throw;
}
}
void my_class::cleanup() {
for(auto &el : my_member)
if(el!=NULL)
delete el;
}
my_class::~my_class()
{
cleanup();
}

Does std::future support polymorphism?

Does std::future in c++ support polymorphism?
So, if to store child_class in future<parent_class>, can I after get it after by dynamic_cast<child_class>?
Providing you use a reference or a pointer (probably obvious since it'll fail to compile otherwise)... Yes.
#include <iostream>
#include <future>
using namespace std;
struct Parent {
virtual void a() { cout << "I am parent"; }
};
struct Child : Parent {
virtual void a() { cout << "I am child"; }
};
Child g_c; //just some global for the purposes of the example
int main() {
std::future<Parent&> p = async(launch::async, []() -> Parent& { return g_c; });
auto c = dynamic_cast<Child&>(p.get());
c.a();
return 0;
}
code result here: http://ideone.com/4Qmjvc

how to correctly initialize a std::vector with type of a struct which contains a std::vector of std::thread

Here is a mini-example of my code, how to correctly initialize member pool_ in the constructor.
#include <vector>
#include <thread>
#include <iostream>
namespace b {
class A;
typedef void (A::*Func) (void);
struct c {
Func fun;
int num;
std::vector<std::thread> threads;
};
class A {
public:
A() {
pool_ = {{&A::func1, 1, }, {&A::func2, 2, }}; // how to initialize?
}
private:
std::vector<c> pool_;
void func1(void) { std::cout << "func1\n"; };
void func2(void) { std::cout << "func2\n"; };
void CreateThread(c& pool) {
for (int i = 0; i < pool.num; ++i) {
pool.threads.push_back(std::thread(pool.fun, this));
}
}
};
} // namespace b
int main() {
b::A a;
return 0;
}
Platform: Ubuntu 14.04 with g++ 4.8.4
compile command:
g++ -Wall -std=c++11 test.cc -lpthread -o test
The major error message is:
error: use of deleted function ‘std::thread::thread(std::thread&)’
I know it is because copy construction and assignment of std::thread is not allowed. But I tried other ways and failed.
Two steps to solving this elegantly:
provide a constructor for c that does 'the right thing'
struct c {
c(Func fun, int num, std::vector<std::thread> threads = {})
: fun(fun)
, num(num)
, threads(std::move(threads))
{}
Func fun;
int num;
std::vector<std::thread> threads;
};
Then neatly emplace your objects into pool_
A()
{
pool_.emplace_back(&A::func1, 1);
pool_.emplace_back(&A::func2, 2);
}

Use temporary variable in initializer_list results in access vialotion error [duplicate]

This question already has an answer here:
Double delete in initializer_list vs 2013
(1 answer)
Closed 8 years ago.
I'm trying to use the initializer_list to instantiate a class, but got wired error.
When try to create a `ClassB``variable using:
ClassB b = { { 1, {} }, { 2, {} };
A memory access violation will occur. However if change to:
ClassA a0, a1;
ClassB b = { { 1, a0 }, { 2, a1 } };
The error disappears.
I tried compile with VC 2013 (without update 1) and gcc-c++ 4.8.1. Using gcc-c++ 4.8.1 doesn't yield any runtime error. Is it an bug in VC?
Can any one help to confirm? Thanks!
Below is the SSCCE:
#include <iostream>
#include <initializer_list>
#include <map>
#include <vector>
#include <memory>
using namespace std;
struct ClassA {
struct Data {
vector<int> vs;
};
unique_ptr<Data> d;
ClassA() : d(new Data()) {}
ClassA(const ClassA& a) : ClassA() {
*d = *(a.d);
}
};
struct ClassB {
ClassB(initializer_list<pair<const int, ClassA> > v) { as = v; }
map<int, ClassA> as;
};
int main() {
ClassA a0, a1;
// ClassB b = { { 1, a0 }, { 2, a1 } }; // won't crash in VC
ClassB b = { { 1, {} }, { 2, {} } };
return 0;
}
The problem is that unique_ptr offers automatic object destruction when the pointer goes out of scope .
if you change
unique_ptr<Data> d;
to
Data * d;
it would work properly :
b.as.begin()->second.d->vs.push_back(1);
I'm not suggesting that this is necessarily the (only) solution and the right way out of this problem .

c++ main() brain teaser

Can you think of a situation where your program would crash without reaching the breakpoint which you set at the beginning of main()?
My answer is during the initialization of static variables, but not sure...
THe above examples are true, but in my experience it's usually due to some problem loading a DLL...
A very simple example
struct abc
{
abc()
{
int* p = 0;
*p = 42; // Drat!
}
};
abc obj;
int main(){}
My answer gives 100% guarantee that this will crash before main().
#include <exception>
struct A
{
A()
{
std::terminate(); //from <exception>
//you can also call std::abort() from <cstdlib>
}
};
A a;
int main(){}
Demo : http://www.ideone.com/JIhcz
Another solution:
struct A
{
A()
{
throw "none";
}
};
A a;
int main(){}
Demo : http://www.ideone.com/daaMe