【问题标题】:Delete causing break on valid struct pointer删除导致有效结构指针中断
【发布时间】:2013-11-02 10:47:12
【问题描述】:

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

//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 部分

感谢大家的建议。

删除[] vs 删除

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

“显示 TICKTYPE”

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

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

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

“三法则”

啊,很可能是这样。

我还没有解决方案,但当我有解决方案时,我会回复。你们都提供了一些好主意,我不再摸不着头脑了。只是埋头工作。敬请期待...

再次感谢。 (PS 'da bomb' 通常是个好东西,但英语的美妙之处在于你可以编造单词并且仍然能够理解重点'一个更精确但无聊的术语应该是 GPF、ASSERT 等。我在交易时需要这些东西有时用 C++... :) 从来没有人在这里谈论过编码的心理......哈哈。”)

第三部分

原来问题出在 memcpy 上。如果我取出所有 memcpy 的对象将被删除。然而,这给我留下了复制的问题。我需要从引用 TICKTYPE& tp 转到指针 TICKTYPE*​​ pTt(参见 QueueEvent)。

我尝试按照下面的酷建议创建一个 Copy 构造函数。如果使用了传统的 copy-ctor,则问题会返回,例如

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

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

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

TICKTYPE*​​ 参考;

然后

pTt = rTt

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

问题

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

我正在考虑对每个结构级别进行 mem 副本,这样 memcpy 复制的任何结构都不会嵌入 struts。你怎么看?好方法?

第四部分

再次感谢所有回复的人。你的建议帮助很大。该问题是在对顶层结构进行 memcpy 时产生的。在主顶层结构中对从属结构进行 memcpy,只要它们又没有从属结构,就不会导致删除失败。我在从属结构上使用了 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) );

等等。

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

【问题讨论】:

  • 显示TICKTYPE的定义。
  • 当有更精确的技术术语可用时,请不要使用“da bomb”之类的短语。
  • 您已经清楚地注释掉了两个delete 行之一。 m_queuedevents是什么类型的?
  • 我来自哪里,如果有什么是“大炸弹”,那是件好事。
  • 在删除之前尝试检查 pTt ia 是否有效。我觉得它已经被那个时候摧毁了。尝试在 ctors 和 dtors 中打印一些调试语句。你可能会得到一些线索。正如答案中所指出的,使用复制 ctors 而不是 memcpy。

标签: c++ heap-memory delete-operator


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    在这种情况下不要使用memcpy。使用复制构造函数。

    TICKTYPE Tt = *pTt;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-22
      • 2012-07-23
      • 2013-12-06
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-02
      相关资源
      最近更新 更多