Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete on a pointer in a Union

Tags:

c++

pointers

I have tried some interesting code(at least for me !). Here it is.

#include <iostream>

struct myStruct{
    int one;

    /*Destructor: Program crashes if the below code uncommented*/
    /*
    ~myStruct(){
        std::cout<<"des\n";
    } 
    */
};
struct finalStruct {
    int noOfChars;
    int noOfStructs;

    union { 
        myStruct *structPtr;
        char *charPtr;
    }U;

};
int main(){
    finalStruct obj;
    obj.noOfChars = 2;
    obj.noOfStructs = 1;
    int bytesToAllocate = sizeof(char)*obj.noOfChars 
                        + sizeof(myStruct)*obj.noOfStructs;

    obj.U.charPtr = new char[bytesToAllocate];
    /*Now both the pointers charPtr and structPtr points to same location*/

    delete []obj.U.structPtr;
}

I have allocated memory to charPtr and deleted with structPtr. It is crashing when I add a destructor to myStruct otherwise no issues.

What exactly happens here. As I know delete[] will call the destructor as many times as number given in new[]. Why it is not crashing when there is no destructor in myStruct?

like image 893
Srikanth Avatar asked Apr 16 '15 10:04

Srikanth


People also ask

What happens when you call delete on a pointer?

This is a common memory management mistake. Once you call delete with a pointer, your program no longer has the right to use the memory the pointer points to.

Can we use pointer in Union?

Pointers to unions? Like structures, we can have pointers to unions and can access members using the arrow operator (->).

Can you delete pointers?

Deleting a pointer does not destruct a pointer actually, just the memory occupied is given back to the OS. You can access it untill the memory is used for another variable, or otherwise manipulated. So it is good practice to set a pointer to NULL (0) after deleting.

Does delete destroy the pointer?

delete keyword in C++Delete is an operator that is used to destroy array and non-array(pointer) objects which are created by new expression.


1 Answers

First off, storing one member of a union and then reading another in the way you're doing it is Undefined Behaviour, plain and simple. It's just wrong and anything could happen.

That aside, it's quite likely the type pun you're attempting with the union actually works (but remember it's not guaranteed). If that's the case, the following happens:

You allocate an array of bytesToAllocate objects of type char and store the address in the unionised pointer.

Then, you call delete[] on the unionised pointer typed as myStruct*. Which means that it assumes it's an array of myStruct objects, and it will invoke the destructor on each of these objects. However, the array does not contain any myStruct objects, it contains char objects. In fact, the size in bytes of the array is not even a multiple of the size of myStruct! The delete implementation must be thoroughly confused. It probably interprets the first sizeof(myStruct) bytes as one myStruct object and calls the destructor in those bytes. Then, there's less than sizeof(myStruct) bytes left, but there are still some left, so the destructor is called on those incomplete bytes, reaches beyond the array, and hilarity ensues.

Of course, since this is just UB, my guess at the behaviour above could be way off. Plain and simple, you've confused it, so it acts confused.

like image 82
Angew is no longer proud of SO Avatar answered Oct 15 '22 10:10

Angew is no longer proud of SO