【发布时间】: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