Search code examples
c++visual-studio-codedynamic-memory-allocationnothrow

Why is new(nothrow) not working on VS Code?


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.


Solution

  • 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.