删除导致有效结构指针中断的原因
Delete causing break on valid struct pointer
我正在为这个挠头。 这要么是那些只有我能看到它就有一个真正简单答案的问题之一,要么是晦涩难懂的陷阱之一。 问题是我在一个函数中更新了一个结构对象,将指针保存到一个取消队列,在另一个函数中检索该指针,然后在使用结构的数据后,尝试删除堆上的对象。 一切都发生在一个类实例中。 这样做时,我得到了炸弹。 我不太清楚为什么。 它是创建时和检索后的有效指针。 我可以写/读它。 但是当试图删除它时,我得到了炸弹。
//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 ) );
可能会将某些资源的所有权分散到本地Tt
和pTt
。当Tt
超出范围时,将调用其析构函数。然后是 pTt
的析构函数,当您调用 delete 时。如果析构函数尝试释放相同的资源,则会出现崩溃。
在这种情况下,请勿使用memcpy
。使用复制构造函数。
TICKTYPE Tt = *pTt;
当指针指向单个元素时,您正在使用数组delete
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 指向成员对象的指针 - 中断线程
- 无法初始化某些指针,在运行时中断程序
- 指针工作,然后似乎无缘无故地中断
- 删除导致有效结构指针中断的原因
- SDL 2通过SpriteManager在屏幕上显示图像,获得指针中断
- 为什么引用在通过指针完成时会中断
- 内存和指针在释放前中断
- 指针错误,在delete[]指针中中断