1

I defined a parent & a child as following:

struct parent
{
    int i;

    ~parent()
    {
        printf("~parent()\n");
    }
};

struct child : public parent
{
    char value[1024*1024];

    ~child()
    {
        printf("~child()\n");
    }
};

int main()
{
    for(int i=0; i < 1000; i++)
    {
        char* child_ptr = new char[sizeof(child)]();
        parent* parent_ptr = reinterpret_cast<parent*>(child_ptr);
        delete parent_ptr;
    }

    return 0;
}

Is above code legal? I mean that does memory leak? I checked with Windows, the memory seems not to be leaked.

duong_dajgja
  • 4,196
  • 1
  • 38
  • 65
  • What is written as output when you run? – thorsan Jun 20 '16 at 09:05
  • windows increase heap for appl's needs – nikniknik2016 Jun 20 '16 at 09:05
  • @thorsan `~parent()` of course – duong_dajgja Jun 20 '16 at 09:07
  • since "value" is not allocated with new, I guess it will be released, but any dynamically allocated memory by child would leak. (?) – thorsan Jun 20 '16 at 09:07
  • 2
    @duong_dajgja, yes offcourse, but I think it should be a part of the question since it is there, it makes the question more complete – thorsan Jun 20 '16 at 09:08
  • `child_ptr` doesn't even point to a valid object so no, it's not legal. And the memory should be released with `delete [] child_ptr`. – molbdnilo Jun 20 '16 at 09:24
  • @thorsan : No, there's no dynamically allocated resource for `child`, simply because no `child` objects are created. The code merely allocates memory which is usable for `placement new`, but until that happens no `child` objects exist. – MSalters Jun 20 '16 at 09:31

4 Answers4

3

The code is flat-out illegal, there's no matching delete[] for the new[]. You have Undefined Behavior, and anything may happen. Speculating what actually happens based on observations is not very productive.

MSalters
  • 173,980
  • 10
  • 155
  • 350
3

Strictly speaking it is an undefined behavior: reinterpret_cast is not the correct one for upcasting. It works, because representations of both child pointer and its base parts are likely to be the same. But in presence of virtual functions, multiple or virtual inheritance, or just some rare archtecture, your code can fail.

Remember: reinterpret_cast is almost always wrong.

Revolver_Ocelot
  • 8,609
  • 3
  • 30
  • 48
1

Like other answers have indicated, if this works, it's by coincidence. By doing delete parent_ptr, you're telling the compiler you want to delete something of type parent, but since the constructor of parent wasn't used to create/allocate this memory, this will result in undefined behavior.

But I'm wondering why you'd want to do this. Do you want to control where the memory of child is allocated? To make that work, you would need to modify your code in a couple of ways:

  • create child through its constructor
  • overload new to fetch memory from where you want it (and if you're doing something special like fetch from a static buffer, overload delete to handle delete correctly)
  • make the destructor of parent virtual so child destructors are also called (even if you have upcasted)

The resulting code may look a bit like this:

struct parent
{
    int i;

    virtual ~parent()
    {
        printf("~parent()\n");
    }
};

struct child : public parent
{
    char value[1024*1024];

    // you probably also want to overload operator new[]
    void * operator new (std::size_t size)
    {
        return new char[size];
    }

    ~child()
    {
        printf("~child()\n");
    }
};


int main()
{
    parent * p = new child(); // no need to cast here (obviously)
    delete p;

    return 0;
}

which prints:

   ~child()
   ~parent()

If this is what you're after, you could also have a look at What uses are there for "placement new"?

Community
  • 1
  • 1
Joris
  • 412
  • 3
  • 8
-1

I suggest you instantiate your structure before you run the program. Please instantiate your structures...something like parent par so that the template (structure) comes to life. You have just declared the structures, but you have not declared any objects of them. Until you declare an object for those structures, they are just mere templates !!

NOTE: Templates in my comment are not referring to the templates concept in C++. They refer to an uninstantiated object only !

Coding Ninja
  • 114
  • 12
  • There's definitely memory allocated, `new char[ ]` does that. You do have a valid criticism though, the constructor definitely should be called. Please note that `template` has a very specific meaning in C++, not the one you use. – MSalters Jun 20 '16 at 09:28
  • To be honest, I see nothing wrong with the loop counter `i`. And it's perfectly normal for dynamically created objects to be undeclared. (Don't confuse declaration of an object and declaration of a pointer) – MSalters Jun 20 '16 at 09:56
  • oops ! He has declared it as `for(int i=0......)`...sorry my bad for not noticing that. I got confused with the one in the structure. However there is absolutely no point in declaring those structures. – Coding Ninja Jun 20 '16 at 10:15