I use a vector as static member of a class to count all the instance of the class itself and its derived classes. However When trying to resize the container I get a stack-overflow thrown from the vector itself.
// initialize static values:
auto_ptr<HandleManager> ID3OBJ::HM = auto_ptr<HandleManager>(new HandleManager());
auto_ptr<vector<shared_ptr<ID3OBJ>>> ID3OBJ::ObjectList = auto_ptr<vector<shared_ptr<ID3OBJ>>>(new vector<shared_ptr<ID3OBJ>>{});
I initialize the static member as empty as shown above.
// constructors:
ID3OBJ::ID3OBJ(double x, double y, double z) : X(x), Y(y), Z(z), Handle(this->HM->addHandle()) { ObjectList->push_back(auto_ptr<ID3OBJ>(this));}
ID3OBJ::ID3OBJ() : X(0), Y(0), Z(0), Handle(this->HM->addHandle()) { ObjectList->push_back(shared_ptr<ID3OBJ>(this));}
Vector::Vector(double x, double y, double z) { X = x; Y = y; Z = z;
ObjectList->push_back(auto_ptr<Vector>(this));}
Vector::Vector() {
X = 0; Y = 0; Z = 0;
ObjectList->push_back(shared_ptr<Vector>(this));}
The constructors add any new instance to the instancelist, which is called ObjectList. This is working as intended.
// deconstructors:
ID3OBJ::~ID3OBJ()
{
string tempH = this->Handle;
auto iter = ObjectList->end();
if (ObjectList->size() == HM->assignedHandles())
{
iter = remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; });
}
ObjectList->erase(iter, ObjectList->end());
this->HM->removeHandle(this->Handle);
}
Vector::~Vector()
{
string tempH = this->Handle;
auto iter = ObjectList->end();
if (ObjectList->size() == HM->assignedHandles())
{
iter=remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; });
}
ObjectList->erase(iter, ObjectList->end());
}
As far as I understand remove_if replaces any occurances whose pred returns true with the element after the occurance. Means if the pred with vec[3] as argument returns true, vec[2] points to vec[4] instead of vec[3]. Hence the erase function is needed to shorten the container length, however as soon as I implement this shortening an error occurs.
Header File:
// class-name: ID3OBJ
// Date: 30.01.2017
// Version: 1.0
// Description: The class works as base class for all used 3D-Objects, and defines the operations all 3D-Objects have, namely the Direction in case of a vector, or origion in all other cases
//
class ID3OBJ
{
public:
double X;
double Y;
double Z;
static auto_ptr<vector<shared_ptr<ID3OBJ>>> ObjectList;
ID3OBJ(double x, double y, double z);
ID3OBJ();
~ID3OBJ();
const string getHandle();
protected:
string Handle;
static auto_ptr<HandleManager> HM;
};
// class-name: I3DM
// Date: 23.03.2017
// Version: 1.0
// Description: The class works as Interface for classes which can do Vector-operations
//
template <class T> class I3DM : public virtual ID3OBJ
{
public:
using ID3OBJ::X;
using ID3OBJ::Y;
using ID3OBJ::Z;
static auto_ptr<vector<shared_ptr<T>>> ObjectList;
protected:
using ID3OBJ::Handle;
using ID3OBJ::HM;
};
// class-name: Vector
// Date: 30.01.2017
// Version: 1.0
// Description: The class works as vector, it provides an interface to acces and modify vectors, aswell as most of the vector operations
//
class Vector : public virtual I3DM<Vector>
{
public:
using I3DM<Vector>::X;
using I3DM<Vector>::Y;
using I3DM<Vector>::Z;
using I3DM<Vector>::ObjectList;
Vector(double x, double y, double z);
Vector();
~Vector();
//I'm not sure if the protected members have to be provided aswell in the header file
protected:
using ID3OBJ::Handle;
using ID3OBJ::HM;
};
HM-header:
class HandleManager
{
public:
HandleManager();
const int assignedHandles();
const string addHandle();
void removeHandle(string hexstring);
protected:
int AssignedHandles;
forward_list<int> FreeHandles;
bool FreeHandlesAvailable;
};
CPP:
const int string_to_hex(string s)
{
int returnvalue;
stringstream stream;
stream << hex << s;
stream >> returnvalue;
return returnvalue;
}
HandleManager::HandleManager()
{
this->FreeHandlesAvailable = false;
this->AssignedHandles = 0;
}
const int HandleManager::assignedHandles()
{
return this->AssignedHandles;
}
const string HandleManager::addHandle()
{
string returnValue;
if (this->FreeHandlesAvailable)
{
returnValue = int_to_hex(this->FreeHandles.front());
this->FreeHandles.pop_front();
this->AssignedHandles++;
if (this->FreeHandles.empty()) { this->FreeHandlesAvailable = false; }
}
else
{
returnValue = int_to_hex(this->AssignedHandles);
this->AssignedHandles++;
if (this->AssignedHandles == 1) { returnValue = int_to_hex((int)0); }
}
return returnValue;
}
void HandleManager::removeHandle(string hexstring)
{
this->FreeHandlesAvailable = true;
this->FreeHandles.push_front(string_to_hex(hexstring));
this->AssignedHandles--;
}
error message:
Unhandled exception at 0x00C01899 in RVE.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x01002F48). occurred
The parameter 0x00000001 is most likely a handle, is there any way to search for the object which has the memory adress given? (0x01002F48)
Consider what happens when you remove an ID3OBJ
from the vector:
auto_ptr<ID3OBJ>
...ID3OBJ
...auto_ptr<ID3OBJ>
from the vector...auto_ptr<ID3OBJ>
... and we go back to step 1.This process will recurse until the stack is overflowed. The same is true for the Vector
vector too. (Roger, Roger. What's your vector, Victor?)
The standard library vector
is not designed to be re-entrant; if a member of vector
winds up calling itself, the behavior is undefined. In your case, vector::erase()
indirectly calls itself through your destructors.
Therefore, your program's behavior is undefined.
auto_ptr<..>(this), shared_ptr<..>(this) or unique_ptr<..>(this) is never correct and a bug waiting to happen. Smart pointers take values from allocated memory, this is pointer to an object and you do not know how it came about. You are effectively doing something like the following,
int a;
auto_ptr< int > ap0( &a ); // certain death.
shared_ptr< int > ap1( &a ); // also certain death.
or equally bad,
auto_ptr< int > ap( new int );
auto_ptr< int > ap0( ap.get() ); // certain death.
shared_ptr< int > ap1( ap.get() ); // also certain death.
It is hard to understand what you are trying to achieve. If you simply want to track instances your vector should definitely be raw pointers. If your purpose is memory management, then I can't see how this could work from your code.
User contributions licensed under CC BY-SA 3.0