4

I wrote the following piece of code to allocate memory for an array:

try {
    int n = 0;
    cin >> n;
    double *temp = new double[n];
    ...
}
catch(exception& e) {
    cout << "Standard exception: " << e.what() << endl;
    exit(1);
}

Of course I'm checking n for negative values etc. but when I enter some large Number over 536*(10^6) I'm not getting a bad-alloc exception but a "Invalid Allocation Size: 4294967295 Bytes" Crash.

E.G. I enter n = 536*(10^6) --> bad-alloc exception I enter n = 537*(10^6) --> Invalid Allocation Size: 4294967295 Bytes --> Crash

Any ideas why this is happening?

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
StarFighter
  • 69
  • 1
  • 8
  • Are you sure you want to allocate 4GB? – Lightness Races in Orbit May 05 '14 at 10:17
  • 1
    running on a 32bit or 64bit process? – MatthiasB May 05 '14 at 10:17
  • I don't always want to allocate that much memory but I dont want my Program to crash if it tries ... Processor is an Intel E8400 with 4GB RAM and Win7 64-bit. I see that I dont have enough memory but I dont understand why it is not giving me a bad-alloc exception. – StarFighter May 05 '14 at 10:20
  • 1
    I think what @MatthiasB and @ Lightness Races in Orbit are trying to tell you is that you are probably trying to allocate to much memory, either more than the system has or more than the OS/CPU can suport. – in need of help May 05 '14 at 10:21
  • 1
    Are you sure it's 536*(10^6) and not 536*(10^7)? Can you call `cout<>n` in order to make sure of that? – barak manos May 05 '14 at 10:22
  • @barak Yes, I made "cout << n" before allocating memory. The integer is right. When I enter numbers > the size of an integer and it runs over my Program just stops because n is negative. – StarFighter May 05 '14 at 10:24
  • I edited the question title to make it clearer, hope that it helps. – Daniel Daranas May 05 '14 at 10:24
  • Oh yes, of course - it is `double` that you are allocating, that's why. 536*(10^6) * sizeof(double) exceeds 4294967295. – barak manos May 05 '14 at 10:25
  • See also this [related question](http://stackoverflow.com/questions/8455658/the-limited-allocation-size-c). – Daniel Daranas May 05 '14 at 10:29

3 Answers3

12

Calling new double[n] calls the global operator new function with a size of n * sizeof(double). If operator new then finds it cannot fulfil the request, it throws an exception.

However, that cannot happen here: the product of n and sizeof(double) is so large that it is actually not possible to call operator new at all, because the size you requested just plain doesn't fit in a size_t. Implementations vary in how they handle this, but yours evidently aborts the program.

If you want to handle this, you can check that n <= SIZE_MAX / sizeof(double) before attempting your allocation.

  • Thanks for this perfect answer, now I got why it is crashing instead of throwing an exception. – StarFighter May 05 '14 at 10:34
  • I'm unable to find any reference about that in the standard. If you know of one, would you mind sharing it? I also can't reproduce this behaviour, I get `bad_alloc` no matter how big is the number. – jrok May 05 '14 at 11:09
  • @jrok The standard failed to define the behaviour prior to C++11, so any behaviour was permitted (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#256). It changed in C++11 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#624, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#805) so that an exception should be thrown (I'm having trouble finding the reference in the standard), but the fact that that is not happening is enough to show that the OP is not using a C++11-conforming implementation. –  May 05 '14 at 12:14
  • @jrok Ah, misread at first, but found it anyway. In C++11, it's 5.3.4p7: "If the value of that *expression* is less than zero or such that the size of the allocated object would exceed the implementation-defined limit, or [...], no storage is obtained and the *new-expression* terminates by throwing an exception of a type that would match a handler (15.3) of type `std::bad_array_new_length` (18.6.2.2)." –  May 05 '14 at 12:19
4

If you are using Visual Studio for building, you may want to enable "large memory allocation" in Linker settings.

Go to project Properties -> Linker -> System -> Enable Large Addresses set to "Yes (/LARGEADDRESSAWARE)"

Martin Perry
  • 9,232
  • 8
  • 46
  • 114
0

On a 32-bit system, your virtual memory address space cannot exceed 2^31-1 (4294967295) bytes.

You are attempting to allocate 536000000*sizeof(double) bytes, which is obviously more than that.

barak manos
  • 29,648
  • 10
  • 62
  • 114
  • This doesn't explain why it doesn't throw `bad_alloc`, which is the exception for when you try to allocate more memory than is available. – Barmar May 05 '14 at 10:35
  • @Barmar: It throws "Invalid Allocation Size: 4294967295 Bytes", which makes perfectly sense, given the allocation size. – barak manos May 05 '14 at 10:37
  • It makes perfect sense, but that's not what your answer says. Your answer says that it's failing because you're trying to exceed your VM space. BTW, I think there's a word missing in the second sentence after "obviously". – Barmar May 05 '14 at 10:42