skip to Main Content

I have written the following code in VScode c++

When I input a really large integer number for n (for example 1000000000000000) I want this output:

"Dynamic memory allocation failed.nProgram will terminate."

If I run the code in VScode with g++ compiler that output is never shown.

However, when I run it in an online compiler like Programiz, the output I want is shown.

The program is as follows:

#include <iostream>
#include <new> 

int main(){
  long int n;
  std::cout << "give n : ";
  std::cin >> n;     
  
  int* a= new (std::nothrow) int[n]; // I expect new to return nullptr
                                     // if the allocation fails          
  
  if (!a) {
    std::cout << "Dynamic memory allocation failed.nProgram will terminate.";
    return -1;
  }

  return 0;
}

So what is the problem?

As I said, in an online compiler when I input for example 1000000000000000 as the value for the integer n the output is the desired:

give n : 1000000000000000
Dynamic memory allocation failed.
Program will terminate.

=== Code Exited With Errors ===

but in VScode the output is :

if ($?) { g++ test.cpp -o test } ; if ($?) { .test }
give n : 1000000000000000
terminate called after throwing an instance of 'std::bad_array_new_length'
  what():  std::bad_array_new_length

What can I do to fix this?

the problem is that I want the program to cout that the dynamic memory allocation failed if the user gives such a huge number for the integer n

I use the GCC C++ compiler (g++) and GDB debugger from mingw-w64.

I downloaded VScode version 1.92 and followed the instructions from their site https://code.visualstudio.com/docs/cpp/config-mingw.

3

Answers


  1. From as-if rule

    New-expression has another exception from the as-if rule: the compiler may remove calls to the replaceable allocation functions even if a user-defined replacement is provided and has observable side-effects.

    so, we might consider that int* a = new (std::nothrow) int[n]; always succeed.

    resulting in program

    int main(){
      long int n;
      std::cout << "give n : ";
      std::cin >> n;
    }
    

    You might see here that clang optimize out the allocation (and didn’t output message) whereas gcc doesn’t optimize and do the call, and so, print the message.

    Login or Signup to reply.
  2. You cannot rely on new returning nullptr if the allocation goes wrong, at least not on recent standard compliant C++ implementations (not sure which standard actually), and (std::nothrow) apparently has no effect non your implementation.

    Instead you should catch and handle exceptions like this:

    #include <iostream>
    #include <new> 
    
    int main() {
      long int n = 1000000000000000;
      int* a;
    
      try
      {
        a = new int[n];
      }
      catch(...)
      {
        // if the allocation fails
        std::cout << "Dynamic memory allocation failed.nProgram will terminate.n";
        return -1;
      }
    
      // do something with a
    
      delete [] a;
      return 0;
    }
    

    Another possibility, maybe more convenient for your use case, is using std::set_new_handler:

    #include <iostream>
    #include <new> 
    #include <cstdlib>
    
    void newhandler()
    {
      std::cout << "Dynamic memory allocation failed.nProgram will terminate.n";
      exit(-1);
      return;
    }
    
    int main() {
      std::set_new_handler(newhandler);
    
      long int n = 1000000000000000;
    
      int *a = new int[n]; // I expect new to return nullptr
    
      // do something with a;
    
      delete [] a;
      return 0;
    }
    

    As soon as new goes wrong, newhandler() will be called, which takes care of displaying your error message and then quits using the exit function.

    Login or Signup to reply.
  3. If you are on Windows, then long int n is a 32-bit integral value, or you build a 32-bit application on other platforms. When you enter 1000000000000000 you get the integer overflow and the negative value -1530494976 in n. new int[n] with a negative value throws std::bad_array_new_length. Note, this exception is not what is disabled by std::nothrow operator new overload.

    https://godbolt.org/z/sf4GKszKd

    Update the declaration long long n or uint64_t n after #include <cstdint>.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search