generic_allocators.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When possible, we implement allocator functions on top of the basic
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// low-level functions malloc() and free().  This way, including a new
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocator is as simple as providing just a small interface.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As such, this file should not contain any allocator-specific code.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implement a C++ style allocation, which always calls the new_handler
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on failure.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void* generic_cpp_alloc(size_t size, bool nothrow) {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* ptr;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = malloc(size);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ptr)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ptr;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!call_new_handler(nothrow))
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ptr;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C++" {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* __cdecl operator new(size_t size) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return generic_cpp_alloc(size, false);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void operator delete(void* p) throw() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(p);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new[](size_t size) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return generic_cpp_alloc(size, false);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void operator delete[](void* p) throw() {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(p);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void* operator new(size_t size, const std::nothrow_t& nt) throw() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return generic_cpp_alloc(size, true);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void* operator new[](size_t size, const std::nothrow_t& nt) throw() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return generic_cpp_alloc(size, true);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function behaves similarly to MSVC's _set_new_mode.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If flag is 0 (default), calls to malloc will behave normally.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If flag is 1, calls to malloc will behave like calls to new,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the std_new_handler will be invoked on failure.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the previous mode.
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int _set_new_mode(int flag) throw() {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_mode = new_mode;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_mode = flag;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return old_mode;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // extern "C++"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void* calloc(size_t n, size_t elem_size) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overflow check
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t size = n * elem_size;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (elem_size != 0 && size / elem_size != n) return NULL;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* result = malloc(size);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != NULL) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(result, 0, size);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void cfree(void* p) __THROW {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(p);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* _recalloc(void* p, size_t n, size_t elem_size) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!p)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return calloc(n, elem_size);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This API is a bit odd.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: recalloc only guarantees zeroed memory when p is NULL.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Generally, calls to malloc() have padding.  So a request
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   to malloc N bytes actually malloc's N+x bytes.  Later, if
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   that buffer is passed to recalloc, we don't know what N
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   was anymore.  We only know what N+x is.  As such, there is
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   no way to know what to zero out.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t size = n * elem_size;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (elem_size != 0 && size / elem_size != n) return NULL;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return realloc(p, size);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* _calloc_impl(size_t n, size_t size) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return calloc(n, size);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef malloc
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef free
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef calloc
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int error_handler(int reportType) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (reportType) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0:  // _CRT_WARN
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      __debugbreak();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1:  // _CRT_ERROR
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      __debugbreak();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:  // _CRT_ASSERT
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      __debugbreak();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* p = NULL;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *p = '\0';
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int _CrtDbgReport(int reportType,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const char*,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int, const char*,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const char*,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ...) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error_handler(reportType);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int _CrtDbgReportW(int reportType,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const wchar_t*,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   int, const wchar_t*,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const wchar_t*,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ...) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error_handler(reportType);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int _CrtSetReportMode(int, int) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* _malloc_dbg(size_t size, int , const char*, int) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return malloc(size);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* _realloc_dbg(void* ptr, size_t size, int, const char*, int) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return realloc(ptr, size);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void _free_dbg(void* ptr, int) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(ptr);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return calloc(n, size);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NDEBUG
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // WIN32
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // extern C
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169