Home | History | Annotate | Download | only in allocator
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // When possible, we implement allocator functions on top of the basic
      6 // low-level functions malloc() and free().  This way, including a new
      7 // allocator is as simple as providing just a small interface.
      8 //
      9 // As such, this file should not contain any allocator-specific code.
     10 
     11 // Implement a C++ style allocation, which always calls the new_handler
     12 // on failure.
     13 inline void* generic_cpp_alloc(size_t size, bool nothrow) {
     14   void* ptr;
     15   for (;;) {
     16     ptr = malloc(size);
     17     if (ptr)
     18       return ptr;
     19     if (!call_new_handler(nothrow))
     20       break;
     21   }
     22   return ptr;
     23 }
     24 
     25 extern "C++" {
     26 
     27 void* __cdecl operator new(size_t size) {
     28   return generic_cpp_alloc(size, false);
     29 }
     30 
     31 void operator delete(void* p) __THROW {
     32   free(p);
     33 }
     34 
     35 void* operator new[](size_t size) {
     36   return generic_cpp_alloc(size, false);
     37 }
     38 
     39 void operator delete[](void* p) __THROW {
     40   free(p);
     41 }
     42 
     43 void* operator new(size_t size, const std::nothrow_t& nt) __THROW {
     44   return generic_cpp_alloc(size, true);
     45 }
     46 
     47 void* operator new[](size_t size, const std::nothrow_t& nt) __THROW {
     48   return generic_cpp_alloc(size, true);
     49 }
     50 
     51 // This function behaves similarly to MSVC's _set_new_mode.
     52 // If flag is 0 (default), calls to malloc will behave normally.
     53 // If flag is 1, calls to malloc will behave like calls to new,
     54 // and the std_new_handler will be invoked on failure.
     55 // Returns the previous mode.
     56 int _set_new_mode(int flag) __THROW {
     57   int old_mode = new_mode;
     58   new_mode = flag;
     59   return old_mode;
     60 }
     61 
     62 }  // extern "C++"
     63 
     64 extern "C" {
     65 
     66 void* calloc(size_t n, size_t elem_size) __THROW {
     67   // Overflow check
     68   const size_t size = n * elem_size;
     69   if (elem_size != 0 && size / elem_size != n) return NULL;
     70 
     71   void* result = malloc(size);
     72   if (result != NULL) {
     73     memset(result, 0, size);
     74   }
     75   return result;
     76 }
     77 
     78 void cfree(void* p) __THROW {
     79   free(p);
     80 }
     81 
     82 #ifdef WIN32
     83 
     84 void* _recalloc(void* p, size_t n, size_t elem_size) {
     85   if (!p)
     86     return calloc(n, elem_size);
     87 
     88   // This API is a bit odd.
     89   // Note: recalloc only guarantees zeroed memory when p is NULL.
     90   //   Generally, calls to malloc() have padding.  So a request
     91   //   to malloc N bytes actually malloc's N+x bytes.  Later, if
     92   //   that buffer is passed to recalloc, we don't know what N
     93   //   was anymore.  We only know what N+x is.  As such, there is
     94   //   no way to know what to zero out.
     95   const size_t size = n * elem_size;
     96   if (elem_size != 0 && size / elem_size != n) return NULL;
     97   return realloc(p, size);
     98 }
     99 
    100 void* _calloc_impl(size_t n, size_t size) {
    101   return calloc(n, size);
    102 }
    103 
    104 #ifndef NDEBUG
    105 #undef malloc
    106 #undef free
    107 #undef calloc
    108 int _CrtDbgReport(int, const char*, int, const char*, const char*, ...) {
    109   return 0;
    110 }
    111 
    112 int _CrtDbgReportW(int, const wchar_t*, int, const wchar_t*,
    113                    const wchar_t*, ...) {
    114   return 0;
    115 }
    116 
    117 int _CrtSetReportMode(int, int) {
    118   return 0;
    119 }
    120 
    121 void* _malloc_dbg(size_t size, int , const char*, int) {
    122   return malloc(size);
    123 }
    124 
    125 void _free_dbg(void* ptr, int) {
    126   free(ptr);
    127 }
    128 
    129 void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
    130   return calloc(n, size);
    131 }
    132 #endif  // NDEBUG
    133 
    134 #endif  // WIN32
    135 
    136 }  // extern C
    137 
    138