/* cxxlib.cc Correct C++ Library Problems Copyright (c) 2000,2001,2002 Kriang Lerdsuwanakij email: lerdsuwa@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "cxxlib.h" #include "cstrlib.h" #if defined STDC_HEADERS # include CXX__HEADER_cstdlib #else # ifdef HAVE_MALLOC_H # include # else void free (); # endif #endif extern char progName[]; #ifdef DEBUG_MEMORY /* Assume machine has size_t >= 32 bits here. */ # define LARGE_MEMORY_THRES 4000000 # define DEBUG_MALLOC #endif void dump_core() { extern string saveCwd; cerr << progName << _(": Check the file BUGREPORT in the package for details\n"); if (saveCwd.size()) k_chdir(saveCwd); abort(); } #ifndef __FreeBSD__ void *operator new (size_t size) CXX__NEW_THROW { #ifdef LARGE_MEMORY_THRES if (size > LARGE_MEMORY_THRES) { cout << flush; // We won't i18n strings here since doing so require // allocating memory cerr << progName << ": new: attempt to allocate " << size << " bytes of memory\n"; dump_core(); } #endif if (size == 0) size = 1; void *p = malloc(size); if (!p) throw BAD_ALLOC(); return p; } void operator delete (void *p) CXX__DELETE_THROW { if (p) // Check if p is not NULL free(p); } #ifdef CXX__HAVE_ARRAY_NEW void *operator new[] (size_t size) CXX__NEW_THROW { #ifdef LARGE_MEMORY_THRES if (size > LARGE_MEMORY_THRES) { cout << flush; // We won't i18n strings here since doing so require // allocating memory cerr << progName << ": new[]: attempt to allocate " << size << " bytes of memory\n"; dump_core(); } #endif if (size == 0) size = 1; void *p = malloc(size); if (!p) throw BAD_ALLOC(); return p; } void operator delete[] (void *p) CXX__DELETE_THROW { if (p) // Check if p is not NULL free(p); } #endif /* CXX__HAVE_ARRAY_NEW */ #endif #ifndef CXX__NEW_THROW_BAD_ALLOC void kcd_new_handler() { throw BAD_ALLOC(); } #endif // // Debugging malloc/calloc/realloc problem // #ifdef DEBUG_MALLOC # include void *(*org_malloc)(size_t) = 0; void *(*org_calloc)(size_t, size_t) = 0; void *(*org_realloc)(void *, size_t) = 0; void *malloc(size_t size) { if (size == 0) // Work-around GCC stack unwinding bug size = 1; if (size > LARGE_MEMORY_THRES) { cout << flush; // We won't i18n strings here since doing so require // allocating memory cerr << progName << ": malloc: attempt to allocate " << size << " bytes of memory\n"; dump_core(); } if (!org_malloc) org_malloc = (void *(*)(size_t))(dlsym(RTLD_NEXT, "malloc")); return (*org_malloc)(size); } void *calloc(size_t nmemb, size_t size) { if (nmemb > LARGE_MEMORY_THRES || size > LARGE_MEMORY_THRES || nmemb == 0 || size == 0) { cout << flush; // We won't i18n strings here since doing so require // allocating memory cerr << progName << ": calloc: attempt to allocate " << nmemb << 'x' << size << " bytes of memory\n"; dump_core(); } if (!org_calloc) org_calloc = (void *(*)(size_t, size_t))(dlsym(RTLD_NEXT, "calloc")); return (*org_calloc)(nmemb, size); } void *realloc(void *ptr, size_t size) { if (size > LARGE_MEMORY_THRES || size == 0) { cout << flush; // We won't i18n strings here since doing so require // allocating memory cerr << progName << ": realloc: attempt to allocate " << size << " bytes of memory\n"; dump_core(); } if (!org_realloc) org_realloc = (void *(*)(void *, size_t))(dlsym(RTLD_NEXT, "realloc")); return (*org_realloc)(ptr, size); } #endif /* DEBUG_MALLOC */ void cxxlib() { #ifndef CXX__NEW_THROW_BAD_ALLOC set_new_handler (kcd_new_handler); #endif }