3

I'm fairly new to C++ so bear with me.

I have the following program to learn about dynamic memory allocation.

#include<iostream>
#include<new>

using namespace std;

int main ()
{
        int i,n;
        int * p;
        cout << "How many numbers would you like to enter? ";
        cin >> i;

        p = new (nothrow) int [i];

        if (NULL == p){
                cout << "Not enough memory!";
        }else{
                for (n=0; n<i; n++){
                        cout << "Enter a number: ";
                        cin >> p[n];
                }
                cout << "You have entered:  ";
                for(n=0; n<i; n++){
                        cout << p[n] << ", ";
                }
                delete[] p;
        }
        return 0;
}

So long as a sensible amount is entered initially the program runs as expected. But when a huge number (1000000000000) is entered I expected the output "Not enough memory" when in fact it starts printing "Enter a Number: " presumably 1000000000000 times, obviously I haven't waited for output. Since this is in the "else" part of the check, why is this happening? I guessed that the comparison isn't working. Any help is appreciated. Thanks.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
Matt Pellegrini
  • 159
  • 1
  • 3
  • 11

3 Answers3

2

If the first number you enter is more 2^31 one of the possible reasons is the following:

After you give invalid data the first time cin becomes in invalid state and each next data input operation (e.g. >> ) does nothing (so it doesn't wait for your input) unless your explicitly return cin to normal state.

One of the possible solutions for you are: add after

cin >> p[n];

this piece of code:

if (cin.fail()) {
   cout << "Bad data" << endl;
   cin.clear();
}
sasha.sochka
  • 14,395
  • 10
  • 44
  • 68
1

Depending on the OS, requests for large blocks of memory may be granted even if there is not enough memory, in the hope that by the time it is needed there will be enough (some process might have released memory it held, or more swap memory might become available). In those systems the call to the allocator will succeed but memory will be handed to the process only on demand (i.e. as you use the memory pages) eventually triggering a fault when the next page cannot be allocated.

This is not really an issue with C++, but with the behavior of the operating system.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Interesting to know, but this doesn't really answer the problem. The program doesn't wait for user input as it would with a granted amount of memory requested, it just starts printing the "Enter a number, over and over without waiting for input. I'm going to look into the answers below and post some results – Matt Pellegrini Jun 24 '13 at 20:54
  • @MattPellegrini It is of crucial importance knowing how to ask questions. The issue seems to be that of an error while parsing the input, but the original question had a number that will parse correctly into an integer in most if not all current architectures. Providing the wrong code or input does not help you get an answer and makes others waste time. – David Rodríguez - dribeas Jun 24 '13 at 22:02
1

First, as somebody already noticed, it could be that 1 billion was actually allocated. It fits in an integer (limit is ~2 billion), and it requires you to have 4gb of memory.

Anyway, before starting printing, I suggest you print the number you have received in input (and then put a pause, one second, or waiting for an input from the user): that value might be different from what you have expected, because it might be too big to be read correctly from cin.

You might therefore want to define i as an unsigned long long.

What is the difference between unsigned long and unsigned long long?

Also, check you are not putting cin in an error state giving a string it cannot parse

Edit from Mooing Duck suggestion:

Use

 if (std::cin >> variable) { }

or

 while(std::cin >> variable) { }

to avoid this problem. Avoid checking .bad(), .fail(), or .eof(), they're often misused, leading to bugs.

Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 1
    Thanks, this solved it, so the number was too big for an int, so the cin wasn't working. Using a long solved this and now outputs "not enough mem" as expected, thanks all – Matt Pellegrini Jun 24 '13 at 21:02
  • I also suggest that you don't name the variable `i`, as it is commonly what you use inside a cycle `for`, try to use meaningful names. – Antonio Jun 24 '13 at 21:03
  • Does anyone no why this behaviour happens? So for example even with the fix, if I enter 's' at the first input, the same thing happens? Why is no error thrown? – Matt Pellegrini Jun 24 '13 at 21:04
  • I would be more careful about the use of i, were this a serious program, it's just for my learning practise and has only these two variables, it's exactly as in the C++ tutorial. – Matt Pellegrini Jun 24 '13 at 21:05
  • What do you mean by destroy? Is there somewhere I can read about this? – Matt Pellegrini Jun 24 '13 at 21:06
  • Like I said, I'm not familiar with C – Matt Pellegrini Jun 24 '13 at 21:06
  • cin is C++ :) If you ask for an integer, a number, and you give a letter, cin will enter an error state. Sorry, the word "destroy" is not quite correct, let's say you pollute it... Give me a second... – Antonio Jun 24 '13 at 21:07
  • 1
    @MattPellegrini: Usually, we use `if (std::cin >> variable) { }` or `while(std::cin >> variable) {` to avoid this problem. Avoid checking `.bad()`, `.fail()`, or `.eof()`, they're often misused, leading to bugs. – Mooing Duck Jun 24 '13 at 21:09
  • @MooingDuck, who are they misused by? That's unfortunate if they are, but that forces the developers to learn to use them right. – Adrian Jun 24 '13 at 21:18
  • What does `bln` stand for? I've never seen that before. – Adrian Jun 24 '13 at 21:22
  • @Adrian: I'd say 99% of the time I've seen them used, they were the source of bugs. For instance, in the code you linked, if the end of the input is reached, that program reads from uninitialized memory, and then goes into an infinite loop. (`bln` is short for "billion".) – Mooing Duck Jun 24 '13 at 21:35
  • Even when those functions are used safely, I find it's _usually_ shorter and easier to understand if you rewrite the code to not use them. – Mooing Duck Jun 24 '13 at 21:37
  • 2
    @Adrian No wait, the code Antonio linked. New rule, each person's name in a conversation must start with a unique letter. – Mooing Duck Jun 24 '13 at 21:55
  • @MooingDuck, lol. True, that is improperly coded, but I don't think that vetoing the use of such functions is the answer. – Adrian Jun 24 '13 at 22:04
  • @Adrian: Since it's usually shorter and easier when they're veto'd, my vote is for veto. :) – Mooing Duck Jun 24 '13 at 22:17
  • @MooingDuck I have edited my answer according to your suggestions, thanks! – Antonio Jun 24 '13 at 22:22