src/dumapp.cpp
/*
* DUMA - Red-Zone memory allocator.
* Copyright (C) 2002-2009 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
* Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
* License: GNU GPL (GNU General Public License, see COPYING-GPL)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* FILE CONTENTS:
* internal implementation file
* replaces various global C++ new/delete/new[]/delete[] operators
*/
#ifndef DUMA_NO_CPP_SUPPORT
#ifdef _MSC_VER
#include <new.h>
#include <new>
#else
#include <new>
#endif
#include <stdlib.h>
#include "dumapp.h"
#include "noduma.h"
/* define the global variables */
static const char unknown_cxx_file[] = "UNKNOWN (use #include \"dumapp.h\")";
#ifndef DUMA_NO_LEAKDETECTION
/* with Leak-Detection */
#define DUMA_PARAMS_UK , unknown_cxx_file, 0
#define DUMA_PARAMS_FILELINE , filename, lineno
#else
/* no Leak-Detection */
#define DUMA_PARAMS_UK
#define DUMA_PARAMS_FILELINE
#endif
/********************************************************************
********************************************************************/
#ifdef _MSC_VER
int DUMA_CDECL duma_new_handler(size_t size) { return 0; }
#else
void duma_new_handler() {}
#endif
// declare function ; needed for attribute
static
#ifdef _MSC_VER
__forceinline
#else
inline
#endif
void *
duma_new_operator(DUMA_SIZE_T userSize, enum _DUMA_Allocator allocator,
bool dothrow
#ifndef DUMA_NO_LEAKDETECTION
,
const char *filename, int lineno
#endif
)
#ifdef __GNUC__
__attribute__((always_inline))
#endif
;
/* Function: duma_new_operator
*
* C++ allocation function,
* which is nearly C++ conform.
*
* Missing features are:
*
* - check if new_handler function hangs, return NULL or throw bad_alloc() in
* this case on UNIX systems alarm() may be usable
*
* Following features are implemented:
*
* - loop is done
* - alignment depends on user
* - bad_alloc() exception will be thrown
* - bad_alloc() is catched to return (void*)0
* - check for userSize == 0, return non-NULL in this case
* implemented in new/delete operators below
*
*/
void *duma_new_operator(DUMA_SIZE_T userSize, enum _DUMA_Allocator allocator,
bool dothrow
#ifndef DUMA_NO_LEAKDETECTION
,
const char *filename, int lineno
#endif
) {
void *ret = 0;
#ifdef _MSC_VER
int pnhret = 1;
#else
#define pnhret 1
#endif
// initialize duma?
if (_duma_g.allocList == 0)
_duma_init(); /* This sets DUMA_ALIGNMENT, DUMA_PROTECT_BELOW, DUMA_FILL,
... */
DUMA_TLSVARS_T *duma_tls = GET_DUMA_TLSVARS();
do {
// try allocation
ret = _duma_allocate(0 /*=alignment*/
,
userSize, duma_tls->PROTECT_BELOW, duma_tls->FILL,
1 /*=protectAllocList*/
,
allocator, DUMA_FAIL_NULL
#ifndef DUMA_NO_LEAKDETECTION
,
filename, lineno
#endif
);
// when allocation failed (and last call to new_handler didn't fail on
// Visual C++)
if (!ret && pnhret) {
// get the current new_handler
#ifdef _MSC_VER
_PNH h = _set_new_handler(duma_new_handler);
_set_new_handler(h);
#else
std::new_handler h = std::set_new_handler(duma_new_handler);
std::set_new_handler(h);
#endif
// is there any handler?
if (h) {
try // new_handler may throw an exception!!!
{
// call handler
#ifdef _MSC_VER
pnhret = h(userSize);
#else
h();
#endif
} catch (std::bad_alloc &) // error occured in new_handler
{
if (dothrow)
throw; // report error via re-throwing
else
return ret; // report error via (void*)0
} // end try catch
} else if (dothrow) // report non-existing handler via exception
throw std::bad_alloc();
else // report non-existing handler via (void*)0
return ret;
}
} while (!ret); // loop until memory is claimed
return ret;
}
/********************************************************************
********************************************************************/
/* Function: operator new
*
* Single object form, no debug information
* (11) = (a) ; ASW
*/
void *DUMA_CDECL operator new(DUMA_SIZE_T size) NEW_THROW_SPEC {
return duma_new_operator(size, EFA_NEW_ELEM, true DUMA_PARAMS_UK);
}
/* Function: operator new
*
* Single object form, no debug information
* (12) = (b) ; ASN
*/
void *DUMA_CDECL operator new(DUMA_SIZE_T size,
const std::nothrow_t &) throw() {
return duma_new_operator(size, EFA_NEW_ELEM, false DUMA_PARAMS_UK);
}
/* Function: operator delete
*
* Single object form, no debug information
* (13) = ( c ) ; FSW
*/
void DUMA_CDECL operator delete(void *ptr) throw() {
#ifndef DUMA_NO_LEAKDETECTION
DUMA_TLSVARS_T &duma_tls = *GET_DUMA_TLSVARS();
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ELEM,
duma_tls.DelFile[duma_tls.DelPtr],
duma_tls.DelLine[duma_tls.DelPtr]);
#else
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ELEM DUMA_PARAMS_UK);
#endif
}
/* Function: operator delete
*
* Single object form, no debug information
* (14) = (d) ; FSN
*/
void DUMA_CDECL operator delete(void *ptr, const std::nothrow_t &) throw() {
#ifndef DUMA_NO_LEAKDETECTION
DUMA_TLSVARS_T &duma_tls = *GET_DUMA_TLSVARS();
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ELEM,
duma_tls.DelFile[duma_tls.DelPtr],
duma_tls.DelLine[duma_tls.DelPtr]);
#else
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ELEM DUMA_PARAMS_UK);
#endif
}
/********************************************************************
********************************************************************/
/* 2x : ARRAY OBJECT FORM - NO DEBUG INFORMATION */
/* Function: operator new[]
*
* Array object form, no debug information
* (21) = (a) ; AAW
*/
void *DUMA_CDECL operator new[](DUMA_SIZE_T size) NEW_THROW_SPEC {
return duma_new_operator(size, EFA_NEW_ARRAY, true DUMA_PARAMS_UK);
}
/* Function: operator new[]
*
* Array object form, no debug information
* (22) = (b) ; AAN
*/
void *DUMA_CDECL operator new[](DUMA_SIZE_T size,
const std::nothrow_t &) throw() {
return duma_new_operator(size, EFA_NEW_ARRAY, false DUMA_PARAMS_UK);
}
/* Function: operator delete[]
*
* Array object form, no debug information
* (23) = (c) ; FAW
*/
void DUMA_CDECL operator delete[](void *ptr) throw() {
#ifndef DUMA_NO_LEAKDETECTION
DUMA_TLSVARS_T &duma_tls = *GET_DUMA_TLSVARS();
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ARRAY,
duma_tls.DelFile[duma_tls.DelPtr],
duma_tls.DelLine[duma_tls.DelPtr]);
#else
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ARRAY DUMA_PARAMS_UK);
#endif
}
/* Function: operator delete[]
*
* Array object form, no debug information
* (24) = (d) ; FAN
*/
void DUMA_CDECL operator delete[](void *ptr, const std::nothrow_t &) throw() {
#ifndef DUMA_NO_LEAKDETECTION
DUMA_TLSVARS_T &duma_tls = *GET_DUMA_TLSVARS();
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ARRAY,
duma_tls.DelFile[duma_tls.DelPtr],
duma_tls.DelLine[duma_tls.DelPtr]);
#else
_duma_deallocate(ptr, 1 /*=protectAllocList*/, EFA_DEL_ARRAY DUMA_PARAMS_UK);
#endif
}
/********************************************************************
********************************************************************/
#ifndef DUMA_NO_LEAKDETECTION
/* 3x : SINGLE OBJECT FORM - WITH DEBUG INFORMATION */
/* Function: operator new
*
* Single object form with debug information
* (31) = (a) ; ASW
*/
void *DUMA_CDECL operator new(DUMA_SIZE_T size, const char *filename,
int lineno) NEW_THROW_SPEC {
return duma_new_operator(size, EFA_NEW_ELEM, true DUMA_PARAMS_FILELINE);
}
/* Function: operator new
*
* Single object form with debug information
* (32) = (b) ; ASN
*/
void *DUMA_CDECL operator new(DUMA_SIZE_T size, const std::nothrow_t &,
const char *filename, int lineno) throw() {
return duma_new_operator(size, EFA_NEW_ELEM, false DUMA_PARAMS_FILELINE);
}
/* Function: operator delete
*
* Single object form with debug information
* (33) = (c) ; FSW
*/
void DUMA_CDECL operator delete(void *ptr, const char *filename,
int lineno) throw() {
_duma_deallocate(ptr, 1 /*=protectAllocList*/,
EFA_DEL_ELEM DUMA_PARAMS_FILELINE);
}
/* Function: operator delete
*
* Single object form with debug information
* (34) = (d) ; FSN
*/
void DUMA_CDECL operator delete(void *ptr, const std::nothrow_t &,
const char *filename, int lineno) throw() {
_duma_deallocate(ptr, 1 /*=protectAllocList*/,
EFA_DEL_ELEM DUMA_PARAMS_FILELINE);
}
/********************************************************************
********************************************************************/
/* 4x : ARRAY OBJECT FORM - WITH DEBUG INFORMATION */
/* Function: operator new[]
*
* Array object form with debug information
* (41) = (a) ; AAW
*/
void *DUMA_CDECL operator new[](DUMA_SIZE_T size, const char *filename,
int lineno) NEW_THROW_SPEC {
return duma_new_operator(size, EFA_NEW_ARRAY, true DUMA_PARAMS_FILELINE);
}
/* Function: operator new[]
*
* Array object form with debug information
* (42) = (b) ; AAN
*/
void *DUMA_CDECL operator new[](DUMA_SIZE_T size, const std::nothrow_t &,
const char *filename, int lineno) throw() {
return duma_new_operator(size, EFA_NEW_ARRAY, false DUMA_PARAMS_FILELINE);
}
/* Function: operator delete[]
*
* Array object form with debug information
* (43) = (c) ; FAW
*/
void DUMA_CDECL operator delete[](void *ptr, const char *filename,
int lineno) throw() {
_duma_deallocate(ptr, 1 /*=protectAllocList*/,
EFA_DEL_ARRAY DUMA_PARAMS_FILELINE);
}
/* Function: operator delete[]
*
* Array object form with debug information
* (44) = (d) ; FAN
*/
void DUMA_CDECL operator delete[](void *ptr, const std::nothrow_t &,
const char *filename, int lineno) throw() {
_duma_deallocate(ptr, 1 /*=protectAllocList*/,
EFA_DEL_ARRAY DUMA_PARAMS_FILELINE);
}
#endif /* end ifdef DUMA_NO_LEAKDETECTION */
#endif /* DUMA_NO_CPP_SUPPORT */