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 
    109 static int error_handler(int reportType) {
    110   switch (reportType) {
    111     case 0:  // _CRT_WARN
    112       __debugbreak();
    113       return 0;
    114 
    115     case 1:  // _CRT_ERROR
    116       __debugbreak();
    117       return 0;
    118 
    119     case 2:  // _CRT_ASSERT
    120       __debugbreak();
    121       return 0;
    122   }
    123   char* p = NULL;
    124   *p = '\0';
    125   return 0;
    126 }
    127 
    128 int _CrtDbgReport(int reportType,
    129                   const char*,
    130                   int, const char*,
    131                   const char*,
    132                   ...) {
    133   return error_handler(reportType);
    134 }
    135 
    136 int _CrtDbgReportW(int reportType,
    137                    const wchar_t*,
    138                    int, const wchar_t*,
    139                    const wchar_t*,
    140                    ...) {
    141   return error_handler(reportType);
    142 }
    143 
    144 int _CrtSetReportMode(int, int) {
    145   return 0;
    146 }
    147 
    148 void* _malloc_dbg(size_t size, int , const char*, int) {
    149   return malloc(size);
    150 }
    151 
    152 void* _realloc_dbg(void* ptr, size_t size, int, const char*, int) {
    153   return realloc(ptr, size);
    154 }
    155 
    156 void _free_dbg(void* ptr, int) {
    157   free(ptr);
    158 }
    159 
    160 void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
    161   return calloc(n, size);
    162 }
    163 #endif  // NDEBUG
    164 
    165 #endif  // WIN32
    166 
    167 }  // extern C
    168 
    169