Copy/pasted tutorial code not behaving properly

Hey,

I copy/pasted the code from this section:

http://www.cplusplus.com/doc/tutorial%20/dynamic/#delete

I'm using Code::Blocks on ubuntu. When I run it and enter a huge number into the first input to try to trigger the error message but instead of displaying the error message it endlessly fills the screen with "Enter number: "

Here's a screenshot of what it looks like in the terminal:

http://i.imgur.com/0HAO40v.png

Here's my version of the code that's in the linked tutorial:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// New Delete
#include <iostream>
#include <new>

int main() {
    int i, n;
    int * p;

    std::cout << "How many numbers would you like to type? ";
    std::cin >> i;
    p = new (std::nothrow) int[i];

    if (p == nullptr)
        std::cout << "Error: memory could not be allocated";
    else {
        for (n = 0; n < i; n++) {
            std::cout << "Enter number: ";
            std::cin >> p[n];
        }

        std::cout << "You have entered: ";

        for (n = 0; n < i; n++) {
            std::cout << p[n];

            if (n != i - 1)
                std::cout << ", ";
        }

        delete[] p;
    }

    return 0;
}


They do the exact same thing but I find typing out the examples and reformatting them helps me remember. Both my version and the one from the tutorial produce the same result I mentioned above. Any idea why? I've tried searching online but I feel like I'm not using the right keywords because I don't understand what's happening

edit: I've been playing around with it and I have more details in the reply post
Last edited on
I set it to cout i and it displayed 2147483647 which wikipedia says is the maximum positive value for a 32-bit signed binary integer. I can understand that but I dont understand why it spams "Enter number: " instead of prompting me to enter 2147483647 numbers.

I tried changing int i int to long long i then told it I wanted to enter a couple hundred trillion numbers. It now says:

 
Error: memory could not be allocated


which is great! That's what i wanted! But if I enter a 20 digit number I get

1
2
3
4
5
terminate called after throwing an instance of 'std::bad_array_new_length'
    what(): std::bad_array_new_length
Aborted (core dumped)

Process returned 134 (0x86)    execution time : 2.186 s


Why am I getting 4 different outcomes when I only want 2?
Last edited on
You tell the standard input you want an integer but you give it a number that's longer than an integer (requires more bits) which breaks the protocol.

The result is that the std::cin sets its failbit (and maybe its badbit), after that you can't read from std::cin as long as failbit or badbit is set and the std::cin statement is just skipped.
You have to clear both of them to be able to read from the input stream again.
std::cin.clear(); sets the bits you want (it does not clear the bits you pass, it sets exactly those!) and resets the rest of the bits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

int main()
{
    int c;
    std::cin >> c;
    // std::cin.clear(std::ios_base::failbit); // sets only failbit
    // std::cin.clear(std::ios_base::badbit); // sets only badbit
    // std::cin.clear(std::ios_base::failbit | std::ios_base::goodbit); // sets failbit and goodbit
    std::cin.clear(); // sets only goodbit (default)
    
    for(int i = 0; i < 10; ++i) {
        std::cout << c;
        std::cin >> c;
    }
}
http://cpp.sh/4etq
Last edited on
Hmm,

I read about .clear() in this section

http://www.cplusplus.com/doc/tutorial/files/#checking_state_flags

but didnt realize it could be applied to cin (which I guess makes sense since it's a stream as well.) I added it after the first std::cin and the program now behaves as expected. I'm not able to trigger the error but it no longer spams enter number.

I guess my other problem is: why am I not able to trigger the error message? Is it because my computer can allocate more memory than an int can ask it for? I tried changing everything to long like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// New Delete
#include <iostream>
#include <new>

int main() {
    long i;
    long * p;

    std::cout << "How many numbers would you like to type? ";
    std::cin >> i;
    std::cin.clear();
    p = new (std::nothrow) long[i];

    if (p == nullptr)
        std::cout << "Error: memory could not be allocated";
    else {
        for (long n = 0; n < i; n++) {
            std::cout << "Enter number: ";
            std::cin >> p[n];
        }

        std::cout << "You have entered: ";

        for (long n = 0; n < i; n++) {
            std::cout << p[n];

            if (n != i - 1)
                std::cout << ", ";
        }

        delete[] p;
    }

    return 0;
}


and I can trigger the error if I enter, say, 10 trillion but if I enter a 30 digit number I still get:

terminate called after throwing an instance of 'std::bad_array_new_length'
    what(): std::bad_array_new_length
Aborted (core dumped)

Process returned 134 (0x86)    execution time : 2.186 s


How come a maxed out int sets its value to its max and a long spits out that error? I've tried searching the error message but the examples I find don't seem to match mine. The tutorial makes it sound like if I enter a large enough number it should trigger the error but that's clearly not the case
Last edited on
This is possibly one of the hazards of using a signed integral type for an array index. First overflowing a signed integral type results in undefined behaviour. What happens if the "size" of your array is negative due to this overflow?


Also be aware that if you try to enter a value larger than the type allows using the extraction operator the stream will fail, and the value of the variable should not change, which means that the value of your "size" variable is undefined, because you never initialized this variable, it could contain any possible value.


You really should be using a size_t for array sizes. The size_t is guaranteed to be able to hold the largest allowable array size.

I get the same result with long and with int.
It works on cpp.sh and on my computer as well.

http://cpp.sh/2etj
How many numbers would you like to type? 3000000000
Error: memory could not be allocated


maybe the compiler behaves differently because it is theoretically impossible for him to create more than a 2^32-1 element large array because you have a 32-bit operating system?

So before trying to allocate he checks if the size exeeds the theoretical maxima?
I don't know what's going on exactly but that's what it looks like.
Last edited on
This is possibly one of the hazards of using a signed integral type for an array index. First overflowing a signed integral type results in undefined behaviour. What happens if the "size" of your array is negative due to this overflow?


That's a good point, I never thought of that before. I'll have to remember that for future programs (and I've changed it for this one.)

Also be aware that if you try to enter a value larger than the type allows using the extraction operator the stream will fail, and the value of the variable should not change, which means that the value of your "size" variable is undefined, because you never initialized this variable, it could contain any possible value.


I don't know if it's compiler or environment specific but if I enter a number that exceeds what the variable can hold then cout the variable it say it equals its max value (4294967295 for an unsigned int and 18446744073709551615 for an unsigned long.)

You really should be using a size_t for array sizes. The size_t is guaranteed to be able to hold the largest allowable array size.


I'll look into that. I was just using the example provided in the tutorial

I get the same result with long and with int.
It works on cpp.sh and on my computer as well.


You're right, it works on cpp.sh but when I try it on my setup it just assigns the maximum possible value to i and asks for a number.

I'm on Ubuntu using Code::Blocks and GCC. I tried changing compilers but I got the same result. I'll try with Code::Blocks on Windows next I guess
Installing GCC on windows was a nightmare and then some random updates killed my video drivers. I should just ask the Code::blocks forums cause it does't seem to be a compiler issue. Thanks for the info!
Or you download QtCreator :b

But what was the problem downloading Gcc?
http://www.mingw.org/category/wiki/download
Topic archived. No new replies allowed.