4

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?

Cœur
  • 32,421
  • 21
  • 173
  • 232

6 Answers6

7

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
  • 159,303
  • 82
  • 478
  • 911
  • 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 Jul 16 '09 at 11:07
  • @Clement H: read sharptooth's answer, you're just repeating what he wrote (slightly incorrectly, even, since you're ignoring the thrown exception). – moswald Jul 16 '09 at 19:30
  • @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 Apr 24 '10 at 07:01
2
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
  • 89,955
  • 22
  • 127
  • 208
0

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
  • 58,120
  • 22
  • 114
  • 192
  • 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 Jul 16 '09 at 11:22
  • Yeah but hes asking about calling Bar with a parameter of 1 which WILL throw an exception. – Goz Jul 16 '09 at 11:24
0

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
  • 29,823
  • 8
  • 40
  • 45
0

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
  • 538
  • 1
  • 10
  • 23
0

Yes, with 0 and 2 you will get memory leaks.


Also this is very bad practice to manage dynamic memory like that. On C++ it's much natural/better way to create a class which will manage memory (for example, in constructor it allocates some memory and in destructor it releases it). This would be more leaks-free and safer

PRIGORYAN
  • 23
  • 7