/* This is -*- C -*- */
/* vim: set sw=2: */
/* $Id: guppi-memory.c,v 1.10 2002/01/15 04:13:42 trow Exp $ */
/*
* guppi-memory.c
*
* Copyright (C) 2000 EMC Capital Management, Inc.
*
* Developed by Jon Trowbridge <trow@gnu.org>.
*
* 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
*/
#include <config.h>
#include "guppi-memory.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <gtk/gtkobject.h>
#ifdef USE_MEMORY_DEBUGGING
static gboolean memtrace_on = FALSE;
static FILE *out = NULL;
#define TRACE_FILE "/tmp/guppi.memtrace"
static void
memtrace (const gchar *file, gint line, gconstpointer ptr, const gchar *op,
const gchar *format_str, ...)
{
va_list args;
if (!memtrace_on && getenv ("GUPPI_MEMORY_TRACE"))
memtrace_on = TRUE;
if (!memtrace_on)
return;
if (out == NULL) {
out = fopen (TRACE_FILE, "w");
if (out) {
fputs ("Writing memory trace to " TRACE_FILE "\n", stderr);
} else {
fputs ("Could not open " TRACE_FILE, stderr);
memtrace_on = FALSE;
return;
}
}
fprintf (out, "%s | %d | %p | %s", file, line, ptr, op);
if (format_str) {
va_start (args, format_str);
fputs (" | ", out);
vfprintf (out, format_str, args);
va_end (args);
}
fputc ('\n', out);
fflush (out);
}
gpointer
_guppi_malloc (gsize N, const gchar *file, gint line)
{
gpointer ptr = g_malloc (N);
memtrace (file, line, ptr, "malloc", "%u", N);
return ptr;
}
gpointer
_guppi_malloc0 (gsize N, const gchar *file, gint line)
{
gpointer ptr = g_malloc0 (N);
memtrace (file, line, ptr, "malloc", "%u", N);
return ptr;
}
gpointer
_guppi_realloc (gpointer x, gsize N, const gchar *file, gint line)
{
gpointer ptr = g_realloc (x, N);
memtrace (file, line, ptr, "realloc", "%p | %u", x, N);
return ptr;
}
void
_guppi_free (gpointer ptr, const gchar *file, gint line)
{
if (ptr == NULL)
return;
memtrace (file, line, ptr, "free", NULL);
g_free (ptr);
}
gpointer
_guppi_new (gsize size, gsize count, const gchar *type,
const gchar *file, gint line)
{
gpointer ptr = g_malloc (size * count);
if (ptr == NULL)
return NULL;
memtrace (file, line, ptr, "new",
"%s | %u | %u | %u", type, size, count, size * count);
return ptr;
}
gpointer
_guppi_new0 (gsize size, gsize count, const gchar *type,
const gchar *file, gint line)
{
gpointer ptr = g_malloc0 (size * count);
if (ptr == NULL)
return NULL;
memtrace (file, line, ptr, "new",
"%s | %u | %u | %u", type, size, count, size * count);
return ptr;
}
gpointer
_guppi_renew (gsize size, gpointer mem, gsize count, const gchar *type,
const gchar *file, gint line)
{
gpointer ptr = g_realloc (mem, size*count);
memtrace (file, line, ptr, "renew", "%p | %s | %u | %u | %u",
mem, type, size, count, size * count);
return ptr;
}
void
_guppi_ref (gpointer ptr, const gchar *file, gint line)
{
gint rc;
if (ptr == NULL)
return;
g_return_if_fail (GTK_IS_OBJECT (ptr));
rc = GTK_OBJECT (ptr)->ref_count;
memtrace (file, line, ptr, "ref",
"%d | %s", rc, gtk_type_name (GTK_OBJECT_TYPE (ptr)));
gtk_object_ref (GTK_OBJECT (ptr));
}
void
_guppi_unref (gpointer ptr, const gchar *file, gint line)
{
gint rc;
if (ptr == NULL)
return;
if (!GTK_IS_OBJECT (ptr)) {
g_warning ("%s:%d _guppi_unref called on non-object (%p)",
file, line, ptr);
return;
}
rc = GTK_OBJECT (ptr)->ref_count;
if (rc <= 0)
g_error ("refcount <= 0 at %s: line %d", file, line);
memtrace (file, line, ptr, "unref",
"%d | %s", rc, gtk_type_name (GTK_OBJECT_TYPE (ptr)));
gtk_object_unref (GTK_OBJECT (ptr));
}
void
_guppi_sink (gpointer ptr, const gchar *file, gint line)
{
if (ptr == NULL)
return;
g_return_if_fail (GTK_IS_OBJECT (ptr));
memtrace (file, line, ptr, "sink",
"%s", gtk_type_name (GTK_OBJECT_TYPE (ptr)));
gtk_object_sink (GTK_OBJECT (ptr));
}
gpointer
_guppi_type_new (GtkType t, const gchar *file, gint line)
{
gpointer ptr;
g_return_val_if_fail (t, NULL);
ptr = gtk_type_new (t);
memtrace (file, line, ptr, "type_new", "%s", gtk_type_name (t));
return ptr;
}
gchar *
_guppi_strdup (const gchar *s, const gchar *file, gint line)
{
gchar *ptr;
if (s == NULL)
return NULL;
ptr = g_strdup (s);
memtrace (file, line, ptr, "malloc", "%s", ptr);
return ptr;
}
gchar *
_guppi_strndup (const gchar *s, guint N, const gchar *file, gint line)
{
gchar *ptr;
if (s == NULL)
return NULL;
ptr = g_strndup (s, N);
memtrace (file, line, ptr, "malloc", "%s", ptr);
return ptr;
}
gchar *
_guppi_strdup_printf (const gchar *file, gint line, const gchar *format, ...)
{
gchar *ptr;
va_list args;
if (format == NULL)
return NULL;
va_start (args, format);
ptr = g_strdup_vprintf (format, args);
memtrace (file, line, ptr, "malloc", "%s", ptr);
va_end (args);
return ptr;
}
gchar *
_guppi_strdup_vprintf (const gchar *file, gint line, const gchar *format,
va_list args)
{
gchar *ptr;
if (format == NULL)
return NULL;
ptr = g_strdup_vprintf (format, args);
memtrace (file, line, ptr, "malloc", "%s", ptr);
return ptr;
}
void
_guppi_strfreev (gchar **s, const gchar *file, gint line)
{
gint i=0;
if (s == NULL)
return;
while (s[i]) {
_guppi_free (s[i], file, line);
++i;
}
_guppi_free (s, file, line);
}
void
_guppi_outside_alloc (gconstpointer p, const gchar *file, gint line)
{
memtrace (file, line, p, "outside", NULL);
}
void
_guppi_outside_object (gconstpointer obj, const gchar *file, gint line)
{
if (obj == NULL)
return;
if (!GTK_IS_OBJECT (obj)) {
g_warning ("guppi_outside_object called on non-object %p at %s, %d",
obj, file, line);
return;
}
if (obj) {
memtrace (file, line, obj, "outside_object", "%s",
gtk_type_name (GTK_OBJECT_TYPE (obj)));
}
}
void
_guppi_permanent_alloc (gconstpointer p, const gchar *file, gint line)
{
memtrace (file, line, p, "permanent", NULL);
}
void
_guppi_A_contains_B (gconstpointer A, gconstpointer B,
const gchar *file, gint line)
{
memtrace (file, line, A, "contains", "%p", B);
}
void
_guppi_finalized (gconstpointer obj, const gchar *file, gint line)
{
if (obj == NULL)
return;
if (!GTK_IS_OBJECT (obj)) {
g_warning ("guppi_finalized called on non-object %p at %s, %d",
obj, file, line);
return;
}
#ifdef OBJECT_AUDIT
object_audit_log_finalize (GTK_OBJECT (obj), file, line);
#endif
memtrace (file, line, obj, "finalized",
"%s", gtk_type_name (GTK_OBJECT_TYPE (obj)));
}
void
guppi_ref_fn (gpointer x)
{
_guppi_ref (x, "??", 0);
}
void
guppi_unref_fn (gpointer x)
{
_guppi_unref (x, "??", 0);
}
void
guppi_free_fn (gpointer x)
{
_guppi_free (x, "??", 0);
}
#else
void
guppi_ref (gpointer x)
{
if (x) {
gtk_object_ref (GTK_OBJECT (x));
}
}
void
guppi_unref (gpointer x)
{
if (x) {
g_assert (GTK_OBJECT (x)->ref_count > 0);
gtk_object_unref (GTK_OBJECT (x));
}
}
void
guppi_sink (gpointer x)
{
if (x) {
gtk_object_sink (GTK_OBJECT (x));
}
}
#endif
void
guppi_memory_trace (gboolean x)
{
#ifdef USE_MEMORY_DEBUGGING
memtrace_on = x;
#else
g_warning ("The memory trace feature is not available.");
#endif
}
/* $Id: guppi-memory.c,v 1.10 2002/01/15 04:13:42 trow Exp $ */
syntax highlighted by Code2HTML, v. 0.9.1