Home > Blockchain >  Undefined behavior or memory leak when using placement new
Undefined behavior or memory leak when using placement new

Time:07-04

I am learning about placement-new in C using the books listed here. Now, to look at some examples, I came across the following snippet in one of the SO post that claims that it(the given example) has undefined behavior:

For example, this has UB:

void ub() {
   alignas(string) char buf[sizeof(string)]; // memory is allocated
   new(buf) string("1");                     // string("1") is constructed
} // memory is deallocated but string("1") outlives the memory!

As you can see the user claims that the above snippet has UB. But i think that it has memory leaks and not UB. Can someone tell me whether the above snippet has UB or memory leak or both and if my understanding(that it has memory leak but not UB) is correct or not.

CodePudding user response:

There is a sentence in the standard which is not very clear about its meaning in [basic.life]/5 saying that if a destructor call is omitted like in your quoted example, then

any program that depends on the side effects produced by the destructor has undefined behavior.

It is not clear what "depends on the side effects" here is supposed to mean. If you consider the side effect of leaking memory something that your program "depends" on, then maybe it applies, but I doubt that this is the intended reading.

There is CWG issue 2523 suggesting to remove this phrase and replace with just a non-normative note mentioning the potential problems of not calling the destructor in such a situation. See also discussion here.

Aside from that, there is no undefined behavior, just a memory leak. Of course with other types than string it could easily be possible to cause undefined behavior if you don't properly call destructors before deallocating their memory.

In practice you should never let this situation happen, even if only to avoid the memory leak. So you can practically treat it almost like undefined behavior.

CodePudding user response:

Nothing really wrong with your code in this case other than the obvious leaking of memory.

The constructor for the type you construct could have side effects though, like adding the constructed object to a global list of all such objects. The destructor would then remove the object from said list but you never call the destructor. So the global list ends up with a dangling pointer.

Note: Modern C has construct_at to replace your placement new.

  • Related