删除导致有效结构指针中断的原因

Delete causing break on valid struct pointer

本文关键字:中断 指针 结构 有效 删除      更新时间:2023-10-16

我正在为这个挠头。 这要么是那些只有我能看到它就有一个真正简单答案的问题之一,要么是晦涩难懂的陷阱之一。 问题是我在一个函数中更新了一个结构对象,将指针保存到一个取消队列,在另一个函数中检索该指针,然后在使用结构的数据后,尝试删除堆上的对象。 一切都发生在一个类实例中。 这样做时,我得到了炸弹。 我不太清楚为什么。 它是创建时和检索后的有效指针。 我可以写/读它。 但是当试图删除它时,我得到了炸弹

//This creates and saves the heap object
void CFoo::QueueEvent( TICKTYPE& tp )
{
    TICKTYPE* pTt = new TICKTYPE;
    memcpy( pTt, &tp, sizeof(tp) );
    m_queuedevents.push_front( pTt );
}
//This retrieves it
int CFoo::ReplayQueuedEvents()
{
    long lSz = m_queuedevents.size();
    for( int i = 0; i < lSz; i++ )
    {
        TICKTYPE Tt;
        TICKTYPE* pTt = m_queuedevents.back();
        //m_queuedevents.pop_back();   //bombs w or w/o this
        //bombs w ot w/o memcpy
        memcpy( &Tt, pTt, sizeof( *pTt ) );
        //int iRtn = SendEvent( Tt );
        ASSERT( SendEvent( Tt ) != ERR_FAILURE );
        //This asserts before or after the memcpy.
        delete[] pTt;
        //delete pTt;
    }

}

第 2 部分

谢谢大家的建议。

删除[] 与删除

我很绝望,所以我也尝试了删除[],而这恰好是我复制的那个。 我已经尝试在两个地方删除,但仍然得到该行为。

"显示刻度类型"

我会展示 TICKTYPE,但现在我看它已经从相当简单发展到相当复杂,其中至少引用了 2 个其他结构。 我必须发布(和格式化)几页代码。 根据下面的评论,我将尝试将其视为崩溃的根源。谢谢。

"在删除之前检查 pTt ia 是否有效。"

在删除之前,我尝试读取和写入它,一切似乎都很好。 此外,Vis Stud在删除之前会在结构中显示有效数据。 在我进一步研究这个问题时,我会牢记这一点。

"三法则"

啊,很可能是这样。

我还没有解决方案,但是当我这样做时,我会回发。 你们都提供了一些好主意,我不再挠头了。 只是膝盖深的工作。 敬请期待...

再次感谢。 (PS "da bomb"通常是一件好事,但英语的美妙之处在于你可以编造单词,但仍然可以理解要点"一个更精确但无聊的术语是GPF,ASSERT等。 有时在处理C++时需要这些东西...... :) 没有人在这里谈论编码的心理学。哈哈》)

第 3 部分

事实证明,问题出在memcpy上。 如果我取出所有内存,则对象将被删除。 但是,这给我留下了复制的问题。 我需要从引用 TICKTYPE&tp 转到指针 TICKTYPE* pTt (参见 QueueEvent)。

我尝试根据下面的很酷的建议创建一个复制构造函数。 如果使用传统的复制器,例如

TICKTYPE( TICKTYPE const& ref )
{
    a = ref.a;
    b= ref.b;
    c = ref.c;
    d= ref.d;
    e = ref.e;  //etc...
}

主结构中有几个结构被深度复制,还有一些 MSFT 结构 FILETIME 和 SYSTEMTIME,我不知道它们是否已经有复制 ctors。

然后是从 ref 到 ptr 的问题。 我尝试了带有签名的复制者

刻度类型* 参考;

然后

pTt = rTt

其中 pTt 是 TICKTYPE*,rTt 是 TICKTYPE rTt。那没有编译。

问题

包含其他结构的结构从 ref 复制到新指针 var(从堆栈复制到堆)的最佳方法是什么。 我想将数据从堆栈移动到堆中,以便进行更永久的存储。

我正在考虑为每个结构级别做一个 mem 副本,这样 memcpy 复制的任何结构都不会嵌入支柱。 你觉得怎么样? 好方法?

第 4 部分

再次感谢所有回复的人。 您的建议帮助很大。 该问题是在对顶级结构进行内存时创建的。 在主顶级结构中对从属结构进行从属结构的监视,只要它们反过来没有从属结构,就不会导致删除失败。 我在从属结构上使用 memcpy,在顶级结构上使用逐个变量副本。 它看起来像这样

TYPE1 foo1;
foo1.a = foo.a
foo1.b = foo.b
foo1.c = foo.c
memcpy( foo1.d, foo.d, sizeof( foo.d) );
memcpy( foo1.e, foo.e, sizeof( foo.e) );

等。

这行得通。 它可能不像其他一些方法那样优雅,但它暂时有效或看起来有效,并且都清楚地记录在主代码正文中,发生了什么,所以它有它的好处。

delete[] pTt;会导致未定义的行为,因为您分配了 new ,而不是new[] 。使用delete .

如果你已经尝试过了,很可能你没有遵守三法则(谷歌一下)。该memcpy( &Tt, pTt, sizeof( *pTt ) );可能会将某些资源的所有权分散到本地TtpTt。当Tt超出范围时,将调用其析构函数。然后是 pTt 的析构函数,当您调用 delete 时。如果析构函数尝试释放相同的资源,则会出现崩溃。

在这种情况下,请勿使用memcpy。使用复制构造函数。

TICKTYPE Tt = *pTt;

当指针指向单个元素时,您正在使用数组delete