C++ how to call D'tor? - c++

I wrote:
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) { // allocation failed for one node (Doesn't throw any exception)
~UnLabeledList();
delete[] SegArray;
throw;
}
SegArray[i] = NOT_INIT;
}
};
};
In case one allocation failed I want to destroy the object (since it has previously allocated nodes) for example when allocation fails at i==5. How can I call the d'tor of UnLabeledListto prevent memory leak?

You should never call a destructor yourself to clean up things. The language rules take care of it.
It is recommended to use standard classes like std::vector and std::list rather than raw arrays/pointers and homebrew lists. The standard classes already take care of exceptions and cleanup, so your class should look something like
class image {
public:
std::list<std::pair<int, int>> UnLabeledList;
std::vector<int> SegArray;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(Segments, NOT_INIT), TotalSegments(Segments) {
for (int i = 0; i < Segments; ++i) {
UnLabeledList.push_back({i, NOT_INIT});
}
};
};

You can't directly invoke the destructor of the UnLabeledList member like that.
If the image constructor throws an uncaught exception, the UnLabeledList member will be destructed automatically, if it was successfully constructed before the exception was thrown.
The correct solution is to implement a clear() method in the linked_list class, which you can call whenever needed, including in the copy constructor and destructor. For example:
template<...>
class linked_list {
// ...
public:
linked_list() {
// initialize the list as needed...
}
linked_list(const linked_list &src) : linked_list() {
for (each node in src) {
if (!push_back(...)) {
clear();
throw ...;
}
}
}
~linked_list() {
clear();
}
linked_list& operator=(const linked_list &rhs) {
// clear and copy the list as needed...
}
void clear() {
// free nodes as needed...
}
node* push_back(...) {
// add new node as needed...
return ...; // nullptr on error
}
//...
};
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw ...; // <-- UnLabeledList::~linked_list() called automatically!
}
SegArray[i] = NOT_INIT;
}
~image() {
delete[] SegArray;
} // <-- UnLabeledList::~linked_list() called automatically!
};
You also can't call a parameter-less throw; outside of an active catch handler. Outside of a catch, you must throw an actual value/object explicitly.
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw std::runtime_error("can't push a new node");
}

Related

How to pass capacity size to lock-free spsc_queue via constructor

I'm wrapping boost::lockfree::spsc_queue<T> queue into a RingBuffer class, and want to be able to use this RingBuffer in my project. But I am having difficulty passing capacity size to queue via class constructor.
RingBuffer.hh
template<class T>
class RingBuffer {
private:
int capacity;
boost::lockfree::spsc_queue<T> queue;
public:
explicit RingBuffer(int size)
{
if(size < 2){
capacity = 2;
} else {
capacity = size;
}
queue(capacity); // Error here. Not working in this way
}
~RingBuffer()
= default;
int Insert(); // queue.push()
int Extract(); // queue.pop()
}
In main.cpp
int main(int argc, char *argv[]) {
auto ringBuffer = new RingBuffer<int>(3); // capacity size: 3
// ...
// other things done
// ...
delete ringBuffer;
return 0;
}
I expect this would work for me, but I get error:
error: type 'boost::lockfree::spsc_queue<int>' does not provide a call operator. # queue(capacity) inside the constructor of RingBuffer.
So, how can I achieve this?
spsc_queue doesn't have operator()(int) in its interface. Now your compiler complains to queue(capacity); - this calls opearator()(int) on queue instance.
I assume your intention is to call ctor of spsc_queue with capacity as argument.
So add helper method to calculate this capacity and pass it to queue constructor on initialization list:
template<class T>
class RingBuffer {
private:
int capacity;
boost::lockfree::spsc_queue<T> queue;
public:
int getCapacity(int size) {
if(size < 2){
capacity = 2;
} else {
capacity = size;
}
return capacity;
}
explicit RingBuffer(int size)
: queue( getCapacity(size) ) // call ctor on initialization list
{
}
~RingBuffer()
= default;
int Insert(); // queue.push()
int Extract(); // queue.pop()
};
Demo

How to make a copy function for a class with vector of pointers?

I have a class, Somec, with a vector of pointers to items. Each item in the vector is from another class type, Myitem.
I want to make a copy function for Somec, but I am having some problems.
Also, I have a copy function for Myitem, do I have to use it in the copy function for Somec?
What I have tried so far:
class Somec {
string Name;
std::vector<Myitem*> Items;
public:
Somec(const Somec& somec); // my copy function
};
/// this the clas to my item :
class Myitem {
Itemk itemk;
public:
// ... some fuction
};
// now I want to make a copy function for Somec
Somec::Somec(const Somec& somec) {
int size = somec.Items.size();
this->Items = new (vector*) (size); // i get an error here
this->Name = somec.Name;
for(int i = 0; i < size; i++) {
*Items.at(i) = *somec.Items.at(i);
}
}
UPDATE: I made the copy function just like Remy Lebeau told me to, but when I try to test this function the code stops working. This is how I am testing it:
class Somec {
string Name;
std::vector<Myitem*> Items;
public:
Somec(const Somec& somec); // my copy function
};
Somec::Somec(const Somec& somec) { // new copy function for somec
int size = somec.Items.size();
this->Name = somec.Name;
for(int i = 0; i < size; i++) {
Items.push_back(new Myitem(*somec.Items[i]));
}
}
// create item function
void Somec::createitem(char* name, const int& Time, const int& level) {
try{
Myitem* ORitem=new Myitem(name, Time, level);
Somec::Items.push_back(ORitem);
}
catch(MemoryProblemException& error) {
throw SomecMemoryProblemException();
}
}
std::vector<Myitem*> Somec::getAllItems() const {
return Items;
}
/// this the class to my item :
class Myitem {
Itemk itemk;
public:
// ... some fuction
};
// my copy function to MYitem
Myitem::Myitem(const Myitem& item){
Myitem* currie = Myitem::clone_item();
curritem->item = itemCopy(item.item);
if (!curritem->item) {
throw itemMemoryProblemException();
return;
}
}
void testCopy() {
Somec somec("name1")
somec.createitem((char*) "item1", 30, 1, 2);
Somec temp(somec);
int x=0;
if ( std::equal(somec.getAllItems().begin() + 1, somec.getAllItems().end(), somec.getAllItems().begin()) ) {
x++;
}
ASSERT_TRUE(x==1);
}
What is my problem? I mean, I did the copy function, I think it is true. But why does the code stop working? Am I testing this in the right way?
My createitem function, I am 100% sure about it, actually.
I am just trying to add items to the the vector in Somec and check if this happened correctly. I learned that in C++, we need a copy constructor, so I wrote one, and thought about testing it since this is my first time doing one.
If you want to copy elements from the vector of the other instance to the vector of your current instance in the copy constructor, then simply do this
class Somec {
string Name;
std::vector<Myitem> Items;
public:
Somec(const Somec& somec); // my copy function
};
i.e. make the vector of values instead of pointers.
If for some reason you have to have to work with pointers, because maybe the copy constructor is deleted or something similar. Then still use this approach, but just don't copy the contents of in the copy constructor, let them get constructed and then assign them
Somec(const Somec& somec) {
this->Items.resize(somec.Items.resize());
for (std::size_t i = 0; i < somec.Items.size(); ++i) {
this->Items[i] = somec.Items[i];
}
// or simply
this->Items = somec.Items;
}
The default compiler-generated copy constructor already does exactly what your copy constructor is doing manually. So it is redundant code.
However, assuming Somec owns the items, then you do need to define a custom copy constructor, and it needs to allocate new Myitem objects and copy the existing data into them, eg:
Somec::Somec(const Somec& somec) {
this->Name = somec.Name;
std::size_t size = somec.Items.size();
this->Items.reserve(size);
for(std::size_t i = 0; i < size; i++) {
Items.push_back(new Myitem(*somec.Items[i]));
}
}
You will have to do something similar in an overriden operator= as well. You can utilize the copy constructor to help you:
Somec& Somec::operator=(const Somec& somec) {
if (&somec != this) {
Somec temp(somec);
std::swap(this->Name, temp.Name);
std::swap(this->Items, temp.Items);
}
return *this;
}
And, of course, make sure you free the owned items in the destructor:
Somec::~Somec() {
std::size_t size = somec.Items.size();
for(std::size_t i = 0; i < size; i++) {
delete Items[i];
}
}
See Rule of Three for more details about why this trio is needed.

Failure handling with destructors vs. catch (...) { fix(); throw; }

Let's say I'm doing something that requires cleanup when an exception is thrown.
For example, say I'm creating a dynamic array, and I need to construct objects, but their constructors may throw an exception:
size_t const n = 100;
T *const p = static_cast<T *>(operator new(sizeof(T) * n));
size_t i;
for (i = 0; i < n; ++i)
new (&p[i]) T(1, 2, 3); // Not exception-safe if T::T(T const &) throws!
I can fix it either via catch (...) { ...; throw; }:
size_t const n = 100;
T *const p = static_cast<T *>(operator new(sizeof(T) * n));
size_t i;
try
{
for (i = 0; i < n; ++i)
new (&p[i]) T(1, 2, 3);
}
catch (...)
{
while (i > 0)
p[--i].~T();
operator delete(p);
throw;
}
or via a scoped destructor:
size_t n = 100;
struct Guard
{
T *p;
size_t i;
Guard(size_t n) : i(), p(static_cast<T *>(operator new(sizeof(T) * n))) { }
~Guard()
{
while (i > 0)
p[--i].~T();
operator delete(p);
}
} guard(n);
for (guard.i = 0; guard.i < n; ++guard.i)
new (&guard.p[guard.i]) T(1, 2, 3);
guard.i = 0; // Successful... "commit" the changes
guard.p = NULL; // or whatever is necessary to commit the changes
Which technique should I prefer to use when, and why?
(Note: This example is only meant to show the difference between two techniques. I know it's not perfect code, so please do not focus on this particular example. It's just for illustration.)
The solution with destructor is better than the explicit try/catch:
it is reusable, if you will need to do similar initialisation in another function, you can just reuse the same guard class
it is easier to maintain - let's say that in some situation your function needs to return with failure but no exception is thrown. With the guard class it is handled more or less automatically
it is cleaner, since the code is more modular
In general, I would say it is a matter of scaling and safety.
The problem with try/catch is two-fold:
safety issue: any early return that ignores the catch (somehow) fails to cleanup
scaling issue: nested try/catch blocks make a mess of the code
scoping issue: to be accessible in the catch the variable must be defined before the try and thus supports default-construction/nullability; it can be painful
Instead, Deferred Statements and Guards do not create unnecessary blocks/scopes and thus no indentation, and read linearly.
Example:
char buffer1[sizeof(T)];
try {
new (buffer1) T(original);
char buffer2[sizeof(T)];
try {
new (buffer2) T(original);
// stuff here
} catch(...) {
reinterpret_cast<T*>(buffer2)->~T();
throw;
}
} catch(...) {
reinterpret_cast<T*>(buffer1)->~T();
throw;
}
Compared to:
char buffer1[sizeof(T)];
new (buffer1) T(original);
Defer const defer1{[&buffer1]() { reinterpret_cast<T*>(buffer1)->~T(); } };
char buffer2[sizeof(T)];
new (buffer2) T(original);
Defer const defer1{[&buffer2]() { reinterpret_cast<T*>(buffer2)->~T(); } };
// stuff here
I would note that it seems a good idea to generalize those:
class Guard {
public:
explicit Guard(std::function<void()> f): _function(std::move(f)) {}
Guard(Guard&&) = delete;
Guard& operator=(Guard&&) = delete;
Guard(Guard const&) = delete;
Guard& operator=(Guard const&) = delete;
~Guard() {
if (not _function) { return; }
try { _function(); } catch(...) {}
}
void cancel() { _function = std::function<void()>{}; }
private:
std::function<void()> _function;
}; // class Guard
class Defer {
public:
explicit Defer(std::function<void()> f): _guard(std::move(f)) {}
private:
Guard _guard;
}; // class Defer

copy local objects by reference

Here's my problem,
Class MClass {
public:
void Add(OtherClass* objects) {
_objects = objects;
}
private:
OtherClass* _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
OtherClass obj[NUMBER_OF_OBJECTS];
//obj initialization here
//...
myObj.Add(obj);
}
It will cause a RT error because the *obj diminishes after the end of the function body.
But, how can make this one valid?
I like to initialized first an object before assigning it to other class.
EDIT
I don't want to use storage classes or something here, I just want a raw array since it is very expensive for me to use. Its functionality will not lessen my problem here.
So how do I do that in a raw-array style?
Class MClass {
public:
void Add(std::vector<OtherClass> objects) {
_objects = std::move(objects);
}
private:
std::vector<OtherClass> _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
myObj.Add(std::move(obj));
}
In your example, you store a pointer to a local array. If the method ends, the array goes out of scope and doesn't exist anymore.
This is the reason, your pointer is not valid anymore. If you want to solve this, learn about the scope of variables in C++.
It is not completely clear what you are trying to do, but you could store a collection of objects instead of a pointer:
class MClass
{
public:
void Add(const std::vector<OtherClass>& objects) {
objects_ = objects;
}
void Add(std::vector<OtherClass>&& objects) {
objects_ = std::move(objects);
}
private:
std::vector<OtherClass> objects_;
};
then
void Setup()
{
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
//obj initialization here
//...
myObj.Add(std::move(obj)); // move obj's contents onto myObs's objects.
}
Stop using raw arrays, and use either std::vector or std::array. Then you don't have to worry about it anymore.
If you really want to do it manually, you have to copy is manually as well. Using e.g. std::vector and std::move is more effective, but here you go:
Class MClass {
public:
MClass()
: _objects(nullptr), _count(0)
{}
MClass(const MClass& other)
: _objects(nullptr), _count(0)
{
Add(other._objects, other._count);
}
~MClass()
{
if (_objects != nullptr)
delete [] _objects;
}
void Add(const OtherClass* objects, const size_t count)
{
if (_objects != nullptr)
delete [] _objects;
_objects = new [count];
for (size_t i = 0; i < count; i++)
_objects[i] = objects[i];
_count = count;
}
MClass& operator=(const MClass& other)
{
Add(other._objects, other._count);
}
private:
OtherClass* _objects;
size_t _count;
};
// ...
myObj.Add(obj, NUMBER_OF_OBJECTS);
As you can see, it's a lot of more code, which makes it harder to follow and debug, and also larger possibility of errors. And not as "effective" as I said above.

why is deleting this object causing problems?

Instantiation:
weapons.push_back(new Pistol());
weapons.push_back(new Rifle());
weapons.push_back(new Shotgun());
destructor, when the first delete happens, the code breaks. This happens when I close the program.
Brain::~Brain()
{
for (unsigned int i = 0; i < weapons.size(); i++)
{
delete weapons[i]; // this is where the code breaks
}
}
I get a warning:
Unhandled exception at 0x0096371f in D3D10DEMO.exe: 0xC0000005: Access violation reading location 0x000002ce.
weapons is this:
weapons(vector<Gun*>())
Edit - I have deleted much of the code from this question but I have also cut down my program so as to reproduce the problem in a much smaller solution here:
http://dl.dropbox.com/u/13519335/D3D10DEMO_0.25.MinRep.zip
You haven't defined virtual destructors for your weapon classes.
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7
You problem is the definition of
class Brain : public Entity
{
private:
std::vector<Gun*> weapons;
and the ownership of Gun* by Brain object.
Brain::~Brain()
{
for (unsigned int i = 0; i < weapons.size(); i++)
{
delete weapons[i];
}
}
If a Brain is copy constructed the delete will be called multiple times deleting the same Gun from different weapons vector. And a Brain temporary is created when you add your Agents (Agent being a derived class of Brain) like so in main function.
int main()
{
Level* level;
std::vector<Agent> agents;
level = new Level(agents);
for (int i = 0; i < 1; i++)
{
//TODO - health is a pointless parameter here
agents.push_back(Agent(100, *level, agents, level->Pickups(), D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f)));
}
delete level;
}
 If you implement a copy constructor for Brain that clones the Gun* vector you should be ok. Alternative you should use shared_ptr<Gun> in your vector so that you don't have to delete them at all.
To summarize your problem boils down to
class Foo{};
class Bar
{
public:
Bar()
{
mFooVec.push_back( new Foo() );
mFooVec.push_back( new Foo() );
}
~Bar()
{
for( unsigned int i = 0;i < mFooVec.size(); ++i )
{
delete mFooVec[i];
}
}
std::vector<Foo*> mFooVec;
};
int main()
{
Bar x;
Bar y = x;
return 0;
}
Here both Bar x and y have the same two Foo* in their mFooVec