c++ - operator new doesn't return 0 when running out of memory -


i found interesting exercise in bruce eckel's thinking in c++, 2nd ed., vol.1 in chapter 13:

/*13. modify nomemory.cpp contains array of int , allocates memory instead of throwing bad_alloc. in main( ), set while loop 1 in newhandler.cpp run out of memory , see happens if operator new not test see if memory allocated. add check operator new , throw bad_alloc*/  #include <iostream> #include <cstdlib> #include <new> // bad_alloc definition using namespace std;  int count = 0;   class nomemory {   int array[100000]; public:   void* operator new(size_t sz) throw(bad_alloc)   {     void* p = ::new char[sz];     if(!p)     {       throw bad_alloc(); // "out of memory"     }     return p;   } };   int main() {    try {     while(1) {       count++;       new nomemory();     }   }   catch(bad_alloc)   {     cout << "memory exhausted after " << count << " allocations!" << endl;     cout << "out of memory exception" << endl;     exit(1);   } } 

my question is: why code not throw bad_alloc, when ran out of memory (as per task manager's resource monitor on win7)? assume global ::new char[sz] never returns 0, if memory full. why? turns win7 os numb, non-responding state once ran out of memory, still keep on trying allocate new space.

(one interesting addition: tryed on ubuntu too: bad_alloc not thrown either, still os not goes frozen dangerous process gets killed before os - smart isn't it?)

your implementation of operator new incorrect.

void* operator new(size_t sz) throw(bad_alloc) {   void* p = ::new char[sz];   if(!p)   {     throw bad_alloc(); // "out of memory"   }   return p; } 

::new throws std::bad_alloc , don't need check return value of p pointer.

if g++'s libstdc++ source, compare pointer null after malloc, should in order simulate this:

_glibcxx_weak_definition void * operator new (std::size_t sz) _glibcxx_throw (std::bad_alloc) {   void *p;    /* malloc (0) unpredictable; avoid it.  */   if (sz == 0)     sz = 1;    while (__builtin_expect ((p = malloc (sz)) == 0, false))     {       new_handler handler = std::get_new_handler ();       if (! handler)         _glibcxx_throw_or_abort(bad_alloc());       handler ();     }    return p; } 

so not return 0 throws exception. reason why don't on linux believe process killed kernel (oom-killer) in such cases.

as @marcglisse pointed may want use nothrow (noexcept) version of new:

_glibcxx_weak_definition void * operator new (std::size_t sz, const std::nothrow_t&) glibcxx_use_noexcept {   void *p;    /* malloc (0) unpredictable; avoid it.  */   if (sz == 0)     sz = 1;    while (__builtin_expect ((p = malloc (sz)) == 0, false))     {       new_handler handler = std::get_new_handler ();       if (! handler)         return 0;       __try         {           handler ();         }       __catch(const bad_alloc&)         {           return 0;         }     }    return p; } 

as see return 0 if allocation fails , catch exceptions can raised new_handler. default new_handler throws std::bad_alloc. in case think oom-killer kill application before something. if question more why killed? recommend read oom killer policy.


Comments

Popular posts from this blog

javascript - Chart.js (Radar Chart) different scaleLineColor for each scaleLine -

apache - Error with PHP mail(): Multiple or malformed newlines found in additional_header -

java - Android – MapFragment overlay button shadow, just like MyLocation button -