What is going on with GCC's nullptr? Is this a bug?

51 views Asked by At

Update: I have been digging in various ways to come to a better understanding of the picture I have demonstrated below(a deliberately buggy program!). I am still learning but hate to move forward with a misunderstanding in my brain. I have found the following link and it seems to lead in a promising direction:

conversion from nullptr_t to bool: valid or not?


I tried testing memory allocated with new and ran into unexpected behavior. I have created code to demonstrate:

#include <iostream>
#include <new>

using namespace std;

int main()
{
    // This section is checking the supposed nullptr assigned when memory allocation fails.
    int i = 2000000000; // Within range of long values.
    int * p2 = new (nothrow) int[i];

    cout << "Allocation innappropriate amount of memory and getting nullptr?" << endl << endl;
    cout << "Pointer address: " << p2 << " --- Value at pointer address: " << *p2 << endl << endl;

    if(p2)
    {
        cout << "True - Pointer address: " << p2 << " --- Value at pointer address: " << *p2 << endl << endl << endl;
    }
    else
    {
        cout << "False -Pointer address: " << p2 << " --- Value at pointer address: " << *p2 << endl << endl << endl;
    }

    // This section is checking how nullptr looks in gcc.
    int * p1 = nullptr;
    cout << "Assigning nullptr to pointer varialble." << endl << endl;

    if(p1)
    {
        cout << "True - Pointer address: " << p1 << " --- Value at pointer address: " << *p1 << endl << endl << endl;

    }
    else
    {
        cout << "False -Pointer address: " << p1 << " --- Accessing value would cause error!" << endl << endl << endl;
    }

}

The output is:

Allocation innappropriate amount of memory and getting nullptr?

Pointer address: 0x1f70783e040 --- Value at pointer address: 0

True - Pointer address: 0x1f70783e040 --- Value at pointer address: 0


Assigning nullptr to pointer varialble.

False -Pointer address: 0 --- Accessing value would cause error!



Process returned 0 (0x0)   execution time : 0.096 s
Press any key to continue.

I can't boolean test the pointer in the second part without dereferencing the pointer which I understand isn't supposed to be necessary. Is this just different interpretation of the standard or is this a bug?

2

There are 2 answers

0
WackEyedWanderer On BEST ANSWER

Finally figured out a couple of things that were causing me confusion.

  1. When you input a number that is too large for the variable(in this case an int) then the maximum value of int seems to be stored in the variable. This allows the program to continue running using this variable.

  2. This value is still messes up std::cin and it goes into an infinite loop. Apparently a fail flag gets set and it can be reset with cin.clear().

I thought this was a problem with pointers. It is instead a case of how c++ will let you be very stupid.

0
n. m. could be an AI On

Is this a bug?

There are several. Not in GCC though, but in your program.

cout << "Allocation innappropriate amount of memory and getting nullptr?" << endl << endl;

The answer to this question depends on what kind of computer you are running this program on and in what exact environment. For a regular unaltered PC, the answer is probably "no".

cout << "Pointer address: " << p2 << " --- Value at pointer address: " << *p2 << endl << endl;

You are dereferencing p2 without checking that it is not nullptr. If it happens to be a nullptr (unlikely on your PC, but likely in other environments) this dereference is undefined behaviour. Moreover, dereferencing a pointer that does not point at an initialised object and reading its value is undefined behaviour.1

cout << "True - Pointer address: " << p2 << " --- Value at pointer address: " << *p2 << endl << endl << endl;
...
cout << "False -Pointer address: " << p2 << " --- Value at pointer address: " << *p2 << endl << endl << endl;

These two statements suffer from the same problem. If p2 is nullptr, then dereferencing it is undefined behaviour because dereferencing a nullptr is undefined behaviour. If it is not, then dereferencing it and reading the value reads an int that has not been initialised, which is undefined behaviour.1

Here is how you might test allocation limits on your computer (live demo):

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <new>

int main()
{    
    for (std::size_t i = 1;  ; i <<= 1)
    {
        std::cout << "Trying to allocate 0x" 
           << std::hex << std::setw(16) << 
           << std::setfill('0') << i << " ints... ";
        auto * p2 = new (std::nothrow) int[i];

        if(p2)
        {
            std::cout << "Success:  p2 is " << p2 << "\n";
        }
        else
        {
            std::cout << "Failure:  p2 is " << p2 << "\n";
            break;
        }
    }
}

Note, not dereferencing the pointer, there isn't anything usable hiding inside.

--

1Or it was in one of the earlier versions of C++, I cannot remember. It is definitely useless though. Don't do that.