* Memento has some experimental code in it to trap new/delete (and
* new[]/delete[] if required) calls.
*
- * In order for this to work, either:
+ * In all cases, Memento will provide a C API that new/delete
+ * operators can be built upon:
+ * void *Memento_cpp_new(size_t size);
+ * void Memento_cpp_delete(void *pointer);
+ * void *Memento_cpp_new_array(size_t size);
+ * void Memento_cpp_delete_array(void *pointer);
*
- * 1) Build memento.c with the c++ compiler.
+ * There are various ways that actual operator definitions can be
+ * provided:
+ *
+ * 1) If memento.c is built with the c++ compiler, then global new
+ * and delete operators will be built in to memento by default.
+ *
+ * 2) If memento.c is built as normal with the C compiler, then
+ * no such veneers will be built in. The caller must provide them
+ * themselves. This can be done either by:
+ *
+ * a) Copying the lines between:
+ * // C++ Operator Veneers - START
+ * and
+ * // C++ Operator Veneers - END
+ * from memento.c into a C++ file within their own project.
*
* or
*
- * 2) Build memento.c as normal with the C compiler, then from any
- * one of your .cpp files, do:
+ * b) Add the following lines to a C++ file in the project:
+ * #define MEMENTO_CPP_EXTRAS_ONLY
+ * #include "memento.c"
*
- * #define MEMENTO_CPP_EXTRAS_ONLY
- * #include "memento.c"
+ * 3) For those people that would like to be able to compile memento.c
+ * with a C compiler, and provide new/delete veneers globally
+ * within their own C++ code (so avoiding the need for memento.h to
+ * be included from every file), define MEMENTO_NO_CPLUSPLUS as you
+ * build, and Memento will not provide any veneers itself, instead
+ * relying on the library user to provide them.
*
- * In the case where MEMENTO is not defined, this will not do anything.
+ * For convenience the lines to implement such veneers can be found
+ * further down this file between:
+ *
+ * Memento's interception of new/delete can be disabled at runtime
+ * by using Memento_setIgnoreNewDelete(1). Alternatively the
+ * MEMENTO_IGNORENEWDELETE environment variable can be set to 1 to
+ * achieve the same result.
*
* Both Windows and GCC provide separate new[] and delete[] operators
* for arrays. Apparently some systems do not. If this is the case for
#include <stdlib.h>
#include <stdarg.h>
+#ifdef __cplusplus
+
+// Avoids problems with strdup()'s throw() attribute on Linux.
+#include <string.h>
+
+extern "C" {
+#endif
+
#define MEMENTO_H
#ifndef MEMENTO_UNDERLYING_MALLOC
void Memento_stats(void);
void *Memento_label(void *, const char *);
void Memento_tick(void);
+int Memento_setVerbose(int verbose);
+int Memento_setIgnoreNewDelete(int ignore);
void *Memento_malloc(size_t s);
void *Memento_realloc(void *, size_t s);
void Memento_bt(void);
+void *Memento_cpp_new(size_t size);
+void Memento_cpp_delete(void *pointer);
+void *Memento_cpp_new_array(size_t size);
+void Memento_cpp_delete_array(void *pointer);
+
+
#ifdef MEMENTO
#ifndef COMPILING_MEMENTO_C
#define Memento_checkBytePointerOrNull(A) 0
#define Memento_checkShortPointerOrNull(A) 0
#define Memento_checkIntPointerOrNull(A) 0
+#define Memento_setVerbose(v) 0
+#define Memento_setIgnoreNewDelete(v) 0
#define Memento_tick() do {} while (0)
#define Memento_startLeaking() do {} while (0)
#endif /* MEMENTO */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* MEMENTO_H */
Novato, CA 94945, U.S.A., +1(415)492-9861, for further information.
*/
+#ifndef MEMENTO_CPP_EXTRAS_ONLY
+
/* Inspired by Fortify by Simon P Bullen. */
/* Set the following if you're only looking for leaks, not memory overwrites
#ifdef MEMENTO
-#ifndef MEMENTO_CPP_EXTRAS_ONLY
-
#ifdef MEMENTO_ANDROID
#include <android/log.h>
Memento_range *squeezes;
int squeezes_num;
int squeezes_pos;
+ int ignoreNewDelete;
} memento;
#define MEMENTO_EXTRASIZE (sizeof(Memento_BlkHeader) + Memento_PostSize)
env = getenv("MEMENTO_VERBOSE");
memento.verbose = (env ? atoi(env) : 1);
+ env = getenv("MEMENTO_IGNORENEWDELETE");
+ memento.ignoreNewDelete = (env ? atoi(env) : 0);
+
atexit(Memento_fin);
Memento_initMutex(&memento.mutex);
return ret;
}
+int Memento_setIgnoreNewDelete(int ignore)
+{
+ int ret = memento.ignoreNewDelete;
+ memento.ignoreNewDelete = ignore;
+ return ret;
+}
+
int Memento_paranoidAt(int i)
{
memento.paranoidAt = i;
return memento.squeezing;
}
-#endif /* MEMENTO_CPP_EXTRAS_ONLY */
-
-#ifdef __cplusplus
-/* Dumb overrides for the new and delete operators */
-
-void *operator new(size_t size)
+void *Memento_cpp_new(size_t size)
{
void *ret;
if (!memento.inited)
Memento_init();
+ if (memento.ignoreNewDelete)
+ return MEMENTO_UNDERLYING_MALLOC(size);
+
if (size == 0)
size = 1;
MEMENTO_LOCK();
return ret;
}
-void operator delete(void *pointer)
+void Memento_cpp_delete(void *pointer)
{
if (!pointer)
return;
+ if (!memento.inited)
+ Memento_init();
+ if (memento.ignoreNewDelete)
+ {
+ MEMENTO_UNDERLYING_FREE(pointer);
+ return;
+ }
+
MEMENTO_LOCK();
do_free(pointer, Memento_EventType_delete);
MEMENTO_UNLOCK();
/* Some C++ systems (apparently) don't provide new[] or delete[]
* operators. Provide a way to cope with this */
-#ifndef MEMENTO_CPP_NO_ARRAY_CONSTRUCTORS
-void *operator new[](size_t size)
+void *Memento_cpp_new_array(size_t size)
{
void *ret;
if (!memento.inited)
if (size == 0)
size = 1;
+
+ if (memento.ignoreNewDelete)
+ return MEMENTO_UNDERLYING_MALLOC(size);
+
MEMENTO_LOCK();
ret = do_malloc(size, Memento_EventType_newArray);
MEMENTO_UNLOCK();
return ret;
}
-void operator delete[](void *pointer)
+void Memento_cpp_delete_array(void *pointer)
{
+ if (memento.ignoreNewDelete)
+ {
+ MEMENTO_UNDERLYING_FREE(pointer);
+ return;
+ }
+
MEMENTO_LOCK();
do_free(pointer, Memento_EventType_deleteArray);
MEMENTO_UNLOCK();
}
-#endif /* MEMENTO_CPP_NO_ARRAY_CONSTRUCTORS */
-#endif /* __cplusplus */
-#else
+#else /* MEMENTO */
/* Just in case anyone has left some debugging code in... */
void (Memento_breakpoint)(void)
{
}
+int (Memento_setIgnoreNewDelete)(int ignore)
+{
+ return 0;
+}
+
+int (Memento_setVerbose)(int verbose)
+{
+ return 0;
+}
+
size_t (Memento_setMax)(size_t max)
{
return 0;
return 0;
}
-#endif
+#endif /* MEMENTO */
+
+#endif /* MEMENTO_CPP_EXTRAS_ONLY */
+
+/* Everything here is only for C++, and then only if we haven't
+ * disabled it. */
+
+#ifndef MEMENTO_NO_CPLUSPLUS
+#ifdef __cplusplus
+
+// C++ Operator Veneers - START
+void *operator new(size_t size)
+{
+ return Memento_cpp_new(size);
+}
+void operator delete(void *pointer)
+{
+ Memento_cpp_delete(pointer);
+}
+void* operator new[](size_t size)
+{
+ return Memento_cpp_new_array(size);
+}
+void operator delete[](void *pointer)
+{
+ Memento_cpp_delete_array(pointer);
+}
+
+/* Some C++ systems (apparently) don't provide new[] or delete[]
+ * operators. Provide a way to cope with this */
+#ifndef MEMENTO_CPP_NO_ARRAY_CONSTRUCTORS
+void *operator new[](size_t size)
+{
+ return Memento_cpp_new_array(size);
+}
+
+void operator delete[](void *pointer)
+{
+ Memento_cpp_delete_array(pointer);
+}
+#endif /* MEMENTO_CPP_NO_ARRAY_CONSTRUCTORS */
+// C++ Operator Veneers - END
+
+#endif /* __cplusplus */
+#endif /* MEMENTO_NO_CPLUSPLUS */