我使用vector作为类的静态成员来计算类本身及其派生类的所有实例。但是当尝试调整容器大小时,我会从向量本身抛出一个堆栈溢出。
// 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>>{});
我将静态成员初始化为空,如上所示。
// 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));}
构造函数将任何新实例添加到实例列表中,该实例列表称为ObjectList。这是按预期工作的。
// 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());
}
据我所知,remove_if将在发生后用元素替换pred返回true的任何出现。意味着如果带有vec [3]作为参数的pred返回true,则vec [2]指向vec [4]而不是vec [3]。 因此需要擦除功能来缩短容器长度,但是一旦实现这种缩短就会发生错误。
标题文件:
// 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-头:
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--;
}
错误消息:
RVE.exe中0x00C01899处的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000001,0x01002F48)。发生
参数0x00000001很可能是一个句柄,有没有办法搜索具有内存地址的对象? (0x01002F48)
答案 0 :(得分:2)
考虑从向量中删除ID3OBJ
时会发生什么:
auto_ptr<ID3OBJ>
... ID3OBJ
... auto_ptr<ID3OBJ>
... auto_ptr<ID3OBJ>
......我们会回到第1步。此过程将递归,直到堆栈溢出。 Vector
向量也是如此。 (Roger,Roger。你的矢量是什么,Victor?)
标准库vector
并非设计为可重入;如果vector
的成员自行调用,则行为未定义。在您的情况下,vector::erase()
通过您的析构函数间接调用自己。
因此,您的程序行为未定义。
答案 1 :(得分:1)
auto_ptr&lt; ..&gt;(this),shared_ptr&lt; ..&gt;(this)或unique_ptr&lt; ..&gt;(this)永远不会正确并且等待发生错误。智能指针从已分配的内存中获取值,此是指向对象的指针,您不知道它是如何产生的。您正在有效地执行以下操作,
int a;
auto_ptr< int > ap0( &a ); // certain death.
shared_ptr< int > ap1( &a ); // also certain death.
或同样糟糕,
auto_ptr< int > ap( new int );
auto_ptr< int > ap0( ap.get() ); // certain death.
shared_ptr< int > ap1( ap.get() ); // also certain death.
很难理解你想要实现的目标。如果你只想跟踪实例,你的向量肯定应该是原始指针。如果您的目的是内存管理,那么我无法从您的代码中了解这是如何工作的。