views:

319

answers:

6
+3  Q: 

С++: memory leaks

Sorry for my English.

The question: At what value of variable n the following code will cause memory leaks?

That's the code:


int* Bar(int n)
{
  if (n == 1)
    throw "exception";
  return new int[n];
}

void Foo(int n)
{
  int *a = Bar(n);
  if (n <= 2)
    return;
  delete[] a;
}

From 5.3.4/7

When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

From 3.7.3.1/2

The effect of dereferencing a pointer returned as a request for zero size is undefined.

Also

Even if the size of the space requested [by new] is zero, the request can fail.

That means you can do it, but you can not legally (in a well defined manner across all platforms) dereference the memory that you get - you can only pass it to array delete - and you should delete it.

Here is an interesting foot-note (i.e not a normative part of the standard, but included for expository puprposes) attached to the sentence from 3.7.3.1/2

[32. The intent is to have operator new() implementable by calling malloc() or calloc(), so the rules are substantially the same. C++ differs from C in requiring a zero request to return a non-null pointer.]

  • And if n is 1 we get:

int *a = Bar(1) and Bar(1) throws exception. Will it be the exception in constructor of variable a? And will it cause memory leaks?

+6  A: 

It can cause them if a == 0 or a == 2.

If a == 1 an exception is thrown and no memory allocated. If a > 2 memory is both allocated and freed.

If a == 0 memory must be allocated since new is not allowed to return null pointers. You must free allocated memory with delete[].

If a == 2 memory is allocated and function returns. That's an obvious leak.

sharptooth
if (n <= 2) return; Seems clear that if n <= 2, delete is never reached. Am I wrong ? Or do you deserve a -1 ? ^^
Clement Herreman
@Clement H: read sharptooth's answer, you're just repeating what he wrote (slightly incorrectly, even, since you're ignoring the thrown exception).
mos
@Clement : Sharptooth meant the same as what you said. It only that he had consider positive values and <= 2, since a -ve value would be converted to size_t which is unsigned , so his response makes absolute sense.
dicaprio
A: 

No, If i understand your question correctly, the bar function will throw the exception and the Foo function never actually catches it which means that it will pass on out of that function as well. But no it shouldn't cause memory leaks because you throw before the allocation is made.

Goz
This isn't Python, although the false indentation makes it look that way. It will only throw if `n==1`, otherwise, it will allocate memory.
Seth Johnson
Yeah but hes asking about calling Bar with a parameter of 1 which WILL throw an exception.
Goz
A: 

Your assessment is mostly correct - n = 2 will cause a memory leak, n = 0 will theoretically result in a memory leak - n = 1 will throw an exception (so new int is never executed), so no memory leak.

Any value for n > 2 will NOT result in a memory leak.

Now if n < 0 - you have undefined behavior - and you may get a memory leak (that is a negative int can be converted to a large positive unsigned value - and bad things may happen)

Faisal Vali
A: 

Since there are no catcher to the exception thrown, it will proceed further and return. But since we declared as a integer pointer, if you send the 'n' as Zero, a default pointer will be created. You can check the size of the pointer as well. But it will not result in any memory leak. The reason behind, when you do a return, since it is a single integer pointer and being a local variable, the memory occupied will be freed by default. So, there will be no memory leak that will happen in the case mentioned by you.

Roopesh Majeti
+2  A: 
If n < 0            you'll more likely get exception std::bad_alloc (because of n will be converted to size_t which is unsigned) - no memory leak.
If n == 1           you'll get exception (invoked by `throw "exception"`) - no memory leak.
If n == 0 || n == 2 you'll never call delete - memory leak.
If n > 2            you'll call delete - no memory leak.
Kirill V. Lyadvinsky
if n<0 Then you may still be able to allocate memory, it depends on other factors weather it will throw bad_alloc.
Martin York
Yes, you could be able theoretically. But most likely that there no such amount of free memory.
Kirill V. Lyadvinsky
A: 

Ok, thanks to all.