views:

87

answers:

2

Is this valid C++ (e.g. not invoking UB) and does it achieve what I want without leaking memory? valgrinds complains about mismatching free and delete but says "no leaks are possible" in the end.

int main() {
  int* a = new int[5];
  for(int i = 0; i < 5; ++i)
    a[i] = i;

  for(int i = 0; i < 5; ++i)
    delete &a[i];
}

The reason I'm asking: I have a class that uses boost::intrusive::list and I new every object that is added to that list. Sometimes I know how many objects I want to add to the list and was thinking about using new[] to allocate a chunk and still be able to delete every object on its own with the Disposer-style of boost::intrusive.

+8  A: 

No way. You cannot call delete on what was not allocated by new or you get heap corruption.

You see, that array created by new[] didn't allocate n individual objects, but one array. The second object of the array is in the middle of the allocation block.

Joshua
Exactly. And, when you allocate something with new (or new[]), it stores a notation in a table somewhere that the particular block of memory is allocated. The corresponding delete (or delete[]) calls will look for that notation.
Brooks Moses
"You cannot call delete on what was not allocated by new or you get heap corruption."You get a crash!
George Edison
+1  A: 

You can add a bit so each object remembers whether it was the first in the contiguous array. This is tricky:

  • totally incompatible with delete object syntax
  • incompatible with inheritance
  • disposer instead calls destructor explicitly, eg object.~ListItem()
  • must still use array operator new[]
  • be sure to dispose objects in reverse order, unlike your included example
  • destructor implements reflective ownership of the array by its first element:

.

ListItem::~ListItem() {
    if ( m_own_my_subarray ) {
        operator delete[]( this ); // does not invoke any destructor!
                 // "this" must be exactly the result of new[]!
    }
}
Potatoswatter
It has to be compatible with inheritance as I use the intrusive::list_base_hooks.
pmr
@pmr: `ListItem` can be inherited from **something** of course, but the destructor must be as shown. For the same reason and in the same sense, C-style arrays of objects are incompatible with inheritance.
Potatoswatter
@pmr: I mean ListItem can *inherit* from something like `list_base_hook`. Could you describe how I'm not answering your question, or acknowledge with an upvote? This isn't an easy kind of question to answer, and I have a pet peeve about knee-jerk "it's impossible" responses…
Potatoswatter
The intention of my comment wasn't to say "it's impossible", I just wanted to add the requirement. I still don't get the "incompatible with inheritance" part of your answer. Did you mean "cannot be extended"?
pmr
@pmr: sorry, the "impossible" thing wasn't referring to you; never mind that. By "incompatible with inheritance" I simply mean that you can't encapsulate the functionality of managing an enclosing array in a base class, at least not with the code I posted. The requirements are essentially the same as those for constructing and destroying the array of objects, which is essentially what you are reimplementing with more basic building blocks.
Potatoswatter