在 C++ 中使用删除命令会导致分段错误吗?

发布于 2024-10-24 12:05:30 字数 993 浏览 5 评论 0原文

我编写了一个程序,它分配类 T 的新对象,如下所示:

T* obj = new T(tid);  

其中 tid 是 int

在我的代码中的其他地方,我试图使用以下方法释放我分配的对象,该对象位于向量内:

delete(myVec[i]);  

然后:

myVec[i] = NULL;

有时它会顺利通过,没有任何错误,而在某些情况下,它会导致崩溃——分段错误。

我在调用删除之前检查过,该对象就在那里——我之前没有在其他地方删除过它。

什么可能导致此崩溃?
这是我将 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 未使用,并且仍然更改整个过程...这里发生了什么?

I've written a program that allocates a new object of the class T like this:

T* obj = new T(tid);  

where tid is an int

Somewhere else in my code, I'm trying to release the object I've allocated, which is inside a vector, using:

delete(myVec[i]);  

and then:

myVec[i] = NULL;

Sometimes it passes without any errors, and in some cases it causes a crash—a segmentation fault.

I've checked before calling delete, and that object is there—I haven't deleted it elsewhere before.

What can cause this crash?
This is my code for inserting objects of the type T to the vector:

_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;  
} 

as it is - the program sometimes crash.
When I replace the push_back line with the commented line, and leave the rest as it is-it works.

but when I replace this code with:

int add() { 

int tid =  _myVec.size();  
    if (newT == NULL){  
        return ERR_CODE;  
    }  
    _myVec.push_back(new T (tid));  

    return tid;  
}  

it crashes in a different stage...

the newT in the second option is unused, and still - changes the whole process... what is going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

够运 2024-10-31 12:05:30

段错误意味着尝试操纵应用程序不应访问的内存位置。

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

  1. 尝试使用指向 NULL 的指针执行某些操作;
  2. 尝试使用未初始化的指针执行某些操作;
  3. 尝试使用指向已删除对象的指针执行某些操作;

1)很容易检查,所以我假设您在使向量中的指针无效时已经这样做了。如果您不进行检查,请在删除调用之前进行检查。这将指出您尝试两次删除对象的情况。
3) 如果将向量中的指针设置为 NULL,则不会发生这种情况。

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

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


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

int tid =  _myVec.size(); 

您正在使用索引作为 id。

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

  1. 您只需将指针设置为 NULL 即可。
  2. 您从向量中删除了指针。

如果你只做 1),那么它应该是安全的(如果你不费心让向量不断增长并且永远不会被释放并且 id 不会被重复使用)。
如果你这样做 2. 那么这都是错误的:每次从向量中删除一个对象时,删除后的对象位置仍然包含的所有对象都会降低 1。使任何存储的 ID/索引无效。

确保你在这一点上保持一致,这肯定​​是错误的根源。

Segfaulting mean trying to manipulate a memory location that shouldn't be accessible to the application.

That means that your problem can come from three cases :

  1. Trying to do something with a pointer that points to NULL;
  2. Trying to do something with an uninitialized pointer;
  3. Trying to do something with a pointer that pointed to a now deleted object;

1) is easy to check so I assume you already do it as you nullify the pointers in the vector. If you don't do checks, then do it before the delete call. That will point the case where you are trying to delete an object twice.
3) can't happen if you set NULL to the pointer in the vector.

2) might happen too. In you case, you're using a std::vector, right? Make sure that implicit manipulations of the vector (like reallocation of the internal buffer when not big enough anymore) doesn't corrupt your list.

So, first check that you delete NULL pointers (note that delete(NULL) will not throw! it's the standard and valid behaviour! ) - in your case you shouldn't get to the point to try to delete(NULL).
Then if it never happen, check that you're not having your vector fill with pointers pointing to trash. For example, you should make sure you're familiar with the [Remove-Erase idiom][1].


Now that you added some code I think I can see the problem :

int tid =  _myVec.size(); 

You're using indice as ids.

Now, all depends on the way you delete your objects. (please show it for a more complete answer)

  1. You just set the pointer to NULL.
  2. You remove the pointer from the vector.

If you only do 1), then it should be safe (if you don't bother having a vector that grows and never get released and ids aren't re-used).
If you do 2. then this is all wrong : each time you remove an object from a vector, all the object still contains after the removed object position will be lowered by one. Making any stored id/index invalid.

Make sure you're coherent on this point, it is certainly a source of errors.

随心而道 2024-10-31 12:05:30

该分段错误很可能是内存访问冲突。一些原因

1) 对象已被释放。确保在删除后将该数组位置设置为 NULL
2)你超出了数组范围
3) 如果您从多个线程访问该数组,请确保正确同步

that segmentation fault is most probably and memory access violation. Some reasons

1) object already deallocated. be sure you set that array position on NULL after delete
2) you are out of array bounds
3) if you access that array from multiple threads make sure you are synchronizing correctly

薄荷港 2024-10-31 12:05:30

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

If you're completely certain that pointer points to a valid object, and that the act of deleting it causes the crash, then you have heap corruption.

请叫√我孤独 2024-10-31 12:05:30

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

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

You should try using a ptr_vector, unlike your code, it's guaranteed to be exception-safe.

Hint: if you write delete, you're doing it wrong

魔法少女 2024-10-31 12:05:30

您无法确定该对象仍然有效:该对象占用的内存不一定会被清除,因此,您可能会看到一些看起来是您的对象的东西,但它不再是您的对象了。

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

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 个字节,您可以轻松验证对象是否已完成其活动。

You can't be sure that the object is still valid: the memory that was occupied by the object is not necessarily cleaned, and therefore, you can be seeing something that appears to be your object but it is not anymore.

You can use a mark in order to be sure that the object is still alive, and delete that mark in the destructor.

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;
}

This way, checking the first 4 bytes in your object you can easily verify whether your object has finished its live or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文