34 static pthread_mutex_t
mutex = PTHREAD_MUTEX_INITIALIZER;
38 static GHashTable * logged;
40 static void str_log (
const char * str,
const char * op,
const char * file,
int line)
43 logged = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
NULL);
45 GList * list = g_hash_table_lookup (logged, str);
46 list = g_list_prepend (list, g_strdup_printf (
"%s by %s:%d", op, file, line));
47 g_hash_table_insert (logged, g_strdup (str), list);
50 static void str_log_dump (
const char * str)
55 for (GList * node = g_hash_table_lookup (logged, str); node; node = node->next)
56 printf (
" - %s\n", (
char *) node->data);
62 * ((
char *) str - 1) = 0;
63 free ((
char *) str - 5);
67 EXPORT
char * str_get_debug (
const char * str,
const char * file,
int line)
76 pthread_mutex_lock (&
mutex);
79 str_log (str,
"get", file, line);
85 if ((copy = g_hash_table_lookup (
table, str)))
87 void * mem = copy - 5;
88 (* (int32_t *) mem) ++;
92 void * mem = malloc (6 + strlen (str));
93 (* (int32_t *) mem) = 1;
95 copy = (
char *) mem + 5;
99 g_hash_table_insert (
table, copy, copy);
102 pthread_mutex_unlock (&
mutex);
107 EXPORT
char * str_ref_debug (
char * str,
const char * file,
int line)
115 pthread_mutex_lock (&
mutex);
119 str_log (str,
"ref", file, line);
122 void * mem = str - 5;
123 (* (int32_t *) mem) ++;
125 pthread_mutex_unlock (&
mutex);
130 EXPORT
void str_unref_debug (
char * str,
const char * file,
int line)
138 pthread_mutex_lock (&
mutex);
142 str_log (str,
"unref", file, line);
145 void * mem = str - 5;
146 if (! -- (* (int32_t *) mem))
147 g_hash_table_remove (
table, str);
149 pthread_mutex_unlock (&
mutex);
154 if (strlen (str) <= len)
158 memcpy (buf, str, len);
168 va_start (args, format);
169 int len = vsnprintf (
NULL, 0, format, args);
174 va_start (args, format);
175 vsnprintf (buf,
sizeof buf, format, args);
183 fprintf (stderr,
"String not in pool: %s\n", str);
190 static void str_leaked (
void * key,
void * str,
void * unused)
192 fprintf (stderr,
"String not freed: %s\n", (
char *) str);
204 g_hash_table_destroy (
table);