user2913447
user2913447

Reputation: 55

Delete causing break on valid struct pointer

I'm scratching my head over this one. This is either one of those issues that has a real simple answer if only I could see it or one of the obscure gotchas. The problem is that I'm newing a struct object in one function, saving the pointer to a dequeue, retrieving that pointer in another func and then once the struct's data has been used, trying to delete the object on the heap. Everything happens in one class instance. When doing that, I get da bomb. I can't quite figure out why. It's a valid pointer at creation and after retrieval. I can write/read to it. But when trying to delete it I get 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;

    }

}

PART 2

Thank you all for your suggestions.

delete[] vs delete

I was desperate so I tried delete[] too and that happened to be the one I copied over. I've tried delete in two places and still get the behavior.

"Show TICKTYPE"

I would show TICKTYPE but now that I look at it it's grown from being fairly simple to fairly complex with references to at least 2 other structs inside of it. I'd have to post a(and format) a couple pages of code. Based on the comments below I'll try looking at that as the source of the crash. Thank you.

"check if pTt ia valid before you delete it."

I've tried reading and writing to it before deleting and all seems OK. Also, Vis Stud shows valid data in the struct right before deleting. I'll keep this in mind as I research this further.

"Rule of three"

Ah, that very well could be the case.

I don't have a solution yet but when I do I will post back. You all have provided some good ideas and I'm no longer scratching my head. Just knee deep in work. Stay tuned...

Thanks again. (PS 'da bomb' is usually a good thing but the beauty of English is you can make words up and still get the point across' A more precise but boring term would have been GPF, ASSERT, etc. I need these things when dealing with C++ sometimes... :) No one ever talks about the psychology of coding here..lol.")

PART 3

It turns out the problem is with the memcpy. If I take out all of the memcpy's the object deletes. However that leaves me with the issue of copying. I need to go from a reference TICKTYPE& tp to pointer TICKTYPE* pTt (See QueueEvent).

I tried creating a Copy constructor per the cool suggestion below. The issue returns if a conventional copy-ctor is used such as

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

There are a couple of structures inside the main struct that get deep copied and there are some MSFT structs FILETIME and SYSTEMTIME that I don't know if they already have copy ctors or not.

Then there's the issue of going from ref to ptr. I tried a copy ctor with signature

TICKTYPE* ref;

then

pTt = rTt

where pTt is TICKTYPE* and rTt is TICKTYPE rTt. That didn't compile.

Question

What's the best way to copy a struct that contains other structs from a ref to a new pointer var (from the stack to the heap). I want to move that data from the stack to the heap for more permanent storage.

I was thinking about doing a mem copy of each struct level such that no struct copied by memcpy would have embedded struts. What do you think? Good approach?

PART 4

Thanks again to all who responded. Your advice helped tremendously. The issue was created when doing a memcpy of the top level struct. Doing memcpy of subordinate structs inside the main, top level struct, as long as they in turn did not have subordinate structs, did not cause delete to fail. I used memcpy on subordinate structs and a variable by variable copy on the top level struct. It looks something like this

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

etc.

That works. It may not be as elegent as some other methods but it works or seems to for the time being and it's all clearly documented in the main code body, what's going on, so it has its benefits.

Upvotes: 0

Views: 895

Answers (2)

youdontneedtothankme
youdontneedtothankme

Reputation: 672

You are using the array-delete when the pointer points to a single element

Upvotes: 2

Luchian Grigore
Luchian Grigore

Reputation: 258598

The delete[] pTt; causes undefined behavior because you allocated it with new, not new[]. Use delete.

If you already tried that, it's probable that you didn't obey the rule of three (google it). The memcpy( &Tt, pTt, sizeof( *pTt ) ); possibly spreads ownership of some resources across the local Tt and the pTt. When Tt goes out of scope, its destructor is called. And then the destructor for pTt, when you call delete. If the destructors attempt to free the same resource, you'll get a crash.

Don't use memcpy in this case. Use the copy constructor.

TICKTYPE Tt = *pTt;

Upvotes: 4

Related Questions