在C ++中使用delete命令会导致分段错误的原因是什么?

时间:2011-03-22 16:16:47

标签: c++ segmentation-fault delete-operator

我编写了一个程序来分配类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;  
}  

它在不同的阶段崩溃......

第二个选项中的newT未使用,仍然 - 改变整个过程......这里发生了什么?

5 个答案:

答案 0 :(得分:15)

Segfaulting意味着尝试操作应用程序无法访问的内存位置。

这意味着您的问题可能来自三种情况:

  1. 尝试使用指向NULL的指针执行某些操作;
  2. 尝试使用未初始化的指针执行某些操作;
  3. 尝试使用指向现在已删除对象的指针执行某些操作;
  4. 1)很容易检查,所以我假设你已经做了,因为你取消了向量中的指针。如果您不进行检查,请在删除调用之前执行此操作。这将指出您尝试两次删除对象的情况。 3)如果向向量中的指针设置NULL,则不会发生。

    2)也可能发生。在你的情况下,你正在使用std :: vector,对吧?确保向量的隐式操作(如内部缓冲区重新分配时不再足够大)不会破坏您的列表。

    所以,首先检查你是否删除了NULL指针(注意删除(NULL)不会抛出!这是标准和有效的行为!) - 在你的情况下你不应该达到这一点尝试删除(NULL)。 然后,如果它永远不会发生,请检查您是否没有使用指针指向垃圾桶的向量填充。例如,你应该确保你熟悉[删除 - 删除习语] [1]。


    现在您添加了一些代码我认为我可以看到问题:

    int tid =  _myVec.size(); 
    

    你使用indice作为id。

    现在,全部取决于您删除对象的方式。(请显示更完整的答案)

    1. 您只需将指针设置为NULL。
    2. 从向量中删除指针。
    3. 如果你只做1),那么它应该是安全的(如果你不打扰一个增长的矢量并且永远不会被释放而且不会重复使用id。)
      如果你做2.那么这是完全错误的:每次从向量中移除一个对象时,所有对象仍然包含在被移除的对象位置将被降低一个之后。使任何存储的id /索引无效。

      确保你在这一点上保持连贯,这肯定是错误的来源。

答案 1 :(得分:1)

最有可能出现分段错误和内存访问冲突。一些原因

1)对象已经解除分配。确保在删除后将该数组位置设置为NULL 2)你超出阵列范围 3)如果从多个线程访问该数组,请确保正确同步

答案 2 :(得分:0)

如果您完全确定指针指向有效对象,并且删除它的行为导致崩溃,那么您就有堆损坏。

答案 3 :(得分:0)

您应该尝试使用ptr_vector,与您的代码不同,它保证是异常安全的。

提示:如果你写delete,你做错了

答案 4 :(得分:0)

您无法确定该对象是否仍然有效:对象占用的内存未必清理,因此,您可能会看到一些看似是您的对象的内容,但现在已不再存在。< / p>

您可以使用标记以确保对象仍然存在,并在析构函数中删除该标记。

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个字节,就可以轻松验证对象是否已完成实时。