C++ 使用C+;中的delete命令会导致分段错误的原因是什么+;?
我编写了一个程序,它分配了类T的一个新对象,如下所示:C++ 使用C+;中的delete命令会导致分段错误的原因是什么+;?,c++,segmentation-fault,delete-operator,C++,Segmentation Fault,Delete Operator,我编写了一个程序,它分配了类T的一个新对象,如下所示: T* obj = new T(tid); 其中,tid是int 在我的代码中的其他地方,我试图释放我分配的对象,它位于向量中,使用: delete(myVec[i]); 然后: myVec[i] = NULL; 有时它通过时没有任何错误,在某些情况下,它会导致崩溃—一个分段错误 在调用delete之前我已经检查过了,那个对象就在那个里——我以前并没有在其他地方删除过它 什么会导致此崩溃? 这是我将T类型的对象插入向量的代码:
T* obj = new T(tid);
其中,tid是int
在我的代码中的其他地方,我试图释放我分配的对象,它位于向量中,使用:
delete(myVec[i]);
然后:
myVec[i] = NULL;
有时它通过时没有任何错误,在某些情况下,它会导致崩溃—一个分段错误
在调用delete之前我已经检查过了,那个对象就在那个里——我以前并没有在其他地方删除过它
什么会导致此崩溃?这是我将T类型的对象插入向量的代码:
_myVec is global
int add() {
int tid = _myVec.size();
T* newT = new T (tid);
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(newT);
// _myVec.push_back(new T (tid));
return tid;
}
实际上,程序有时会崩溃。当我用注释行替换push_back行时,剩下的就保持原样了 但当我将此代码替换为:
int add() {
int tid = _myVec.size();
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(new T (tid));
return tid;
}
它在不同的阶段崩溃
第二个选项中的蝾螈未使用,仍然会改变整个过程。。。这是怎么回事?分段故障意味着试图操作应用程序不应访问的内存位置 这意味着您的问题可能来自三种情况:
现在,您添加了一些代码,我想我可以看到问题:
int tid = _myVec.size();
您正在使用indice作为ID
现在,这一切都取决于您删除对象的方式。(请展示它以获得更完整的答案)
如果你做2。那么这一切都是错误的:每次从向量中移除对象时,移除对象位置后仍然包含的所有对象都将降低一。使任何存储的id/索引无效
请确保您在这一点上是一致的,这肯定是错误的来源。分段错误最有可能是内存访问冲突。一些原因 1) 对象已解除分配。请确保在删除后将该数组位置设置为NULL 2) 您超出了数组边界
3) 如果您从多个线程访问该数组,请确保正确同步。如果您完全确定指针指向有效对象,并且删除该指针会导致崩溃,那么您的堆已损坏。您应该尝试使用,与您的代码不同,它保证是异常安全的
提示:如果写入
delete
,则操作错误您无法确定对象是否仍然有效:对象占用的内存不一定会被清除,因此,您可以看到看似是您的对象但不再是的对象
可以使用标记来确保对象仍然处于活动状态,并在析构函数中删除该标记
class A {
public:
static const unsigned int Inactive;
static const unsigned int Active;
A();
~A();
/* more things ...*/
private:
unsigned int mark;
};
const unsigned int A::Inactive = 0xDEADBEEF;
const unsigned int A::Active = 0x11BEBEEF;
A::A() : mark( Active )
{}
A::~A()
{
mark = Inactive;
}
这样,,检查对象中的前4个字节,您可以轻松验证对象是否已完成活动。您确定索引点位于有效的数组项上吗?要回答此问题,我们需要查看
myVec
的定义以及如何将元素插入其中。这可能是由几乎任何类型的指针引起的错误或缓冲区溢出,因此仅提供信息无助于发现问题。您是否可以访问Valgrind之类的工具?如果是STL向量,请使用erase
或std::remove
。。。需要更多相关的代码和/或调用堆栈才能知道问题所在。您可能还需要检查析构函数中是否出现故障。delete(T*)0
是完全安全的(或者是标准要求的),因此在调用delete
之前不需要检查。我的意思是,在他的特定情况下,他不应该达到这一点(我确实说过它是有效的,可能不清楚,我会解决这个问题)。如果他到达删除NULL的点,那么这意味着让进程到达那里的算法试图在对象死的时候销毁它认为应该是活的对象。管理向量的对象应该确保永远不会发生这种情况,通过这样做,使对象的使用更加安全。我不明白,不管seg如何。错误-我上面提到的使用push_back的三个选项之间有什么区别,为什么它们都会导致程序的不同行为?