Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用C+;中的delete命令会导致分段错误的原因是什么+;?_C++_Segmentation Fault_Delete Operator - Fatal编程技术网

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

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的一个新对象,如下所示:

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;  
}  
它在不同的阶段崩溃


第二个选项中的蝾螈未使用,仍然会改变整个过程。。。这是怎么回事?

分段故障意味着试图操作应用程序不应访问的内存位置

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

  • 试图使用指向NULL的指针执行某些操作
  • 尝试使用未初始化的指针执行某些操作
  • 试图使用指向已删除对象的指针执行某些操作 1) 很容易检查,所以我假设您已经在为向量中的指针置零时进行了检查。如果不进行检查,请在删除调用之前进行检查。这将指向您尝试删除一个对象两次的情况。 3) 如果将向量中的指针设置为NULL,则不会发生这种情况

    2) 可能也会发生。在您的例子中,您使用的是std::vector,对吗?确保对向量的隐式操作(如当不够大时重新分配内部缓冲区)不会损坏列表

    因此,首先检查是否删除空指针(注意delete(NULL)不会抛出!这是标准且有效的行为!)-在您的情况下,您不应该直接尝试删除(NULL)。 然后,如果它从未发生过,请检查向量是否没有被指向垃圾的指针填充。例如,您应该确保熟悉[Remove Erase idiom][1]


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

    int tid =  _myVec.size(); 
    
    您正在使用indice作为ID

    现在,这一切都取决于您删除对象的方式。(请展示它以获得更完整的答案)

  • 您只需将指针设置为NULL
  • 从向量中删除指针
  • 如果你只做1),那么它应该是安全的(如果你不介意有一个不断增长、永远不会被释放的向量,并且不使用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的三个选项之间有什么区别,为什么它们都会导致程序的不同行为?