2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 inspired by http://swapped.cc/halloc/
31 if you need to build this outside of the Samba source tree then please define _STANDALONE_
43 #define MAX_TALLOC_SIZE 0x10000000
44 #define TALLOC_MAGIC 0xe814ec4f
45 #define TALLOC_MAGIC_FREE 0x7faebef3
46 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
48 /* by default we abort when given a bad pointer (such as when talloc_free() is called
49 on a pointer that came from malloc() */
51 #define TALLOC_ABORT(reason) abort()
54 #ifndef discard_const_p
55 #define discard_const_p(type, ptr) ((type *)(ptr))
58 /* this null_context is only used if talloc_enable_leak_report() or
59 talloc_enable_leak_report_full() is called, otherwise it remains
62 static const void *null_context;
65 struct talloc_reference_handle {
66 struct talloc_reference_handle *next, *prev;
70 typedef int (*talloc_destructor_t)(void *);
73 struct talloc_chunk *next, *prev;
74 struct talloc_chunk *parent, *child;
75 struct talloc_reference_handle *refs;
78 talloc_destructor_t destructor;
82 /* panic if we get a bad magic value */
83 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
85 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
86 if (tc->magic != TALLOC_MAGIC) {
87 if (tc->magic == TALLOC_MAGIC_FREE) {
88 TALLOC_ABORT("Bad talloc magic value - double free");
90 TALLOC_ABORT("Bad talloc magic value - unknown value");
97 /* hook into the front of the list */
98 #define _TLIST_ADD(list, p) \
102 (p)->next = (p)->prev = NULL; \
104 (list)->prev = (p); \
105 (p)->next = (list); \
111 /* remove an element from a list - element doesn't have to be in list. */
112 #define _TLIST_REMOVE(list, p) \
114 if ((p) == (list)) { \
115 (list) = (p)->next; \
116 if (list) (list)->prev = NULL; \
118 if ((p)->prev) (p)->prev->next = (p)->next; \
119 if ((p)->next) (p)->next->prev = (p)->prev; \
121 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
126 return the parent chunk of a pointer
128 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
130 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
131 while (tc->prev) tc=tc->prev;
136 Allocate a bit of memory as a child of an existing pointer
138 void *_talloc(const void *context, size_t size)
140 struct talloc_chunk *tc;
142 if (context == NULL) {
143 context = null_context;
146 if (size >= MAX_TALLOC_SIZE) {
150 tc = malloc(sizeof(*tc)+size);
151 if (tc == NULL) return NULL;
154 tc->magic = TALLOC_MAGIC;
155 tc->destructor = NULL;
161 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
166 parent->child->parent = NULL;
169 _TLIST_ADD(parent->child, tc);
171 tc->next = tc->prev = tc->parent = NULL;
174 return (void *)(tc+1);
179 setup a destructor to be called on free of a pointer
180 the destructor should return 0 on success, or -1 on failure.
181 if the destructor fails then the free is failed, and the memory can
182 be continued to be used
184 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
186 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
187 tc->destructor = destructor;
191 increase the reference count on a piece of memory.
193 void talloc_increase_ref_count(const void *ptr)
195 talloc_reference(null_context, ptr);
199 helper for talloc_reference()
201 static int talloc_reference_destructor(void *ptr)
203 struct talloc_reference_handle *handle = ptr;
204 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
205 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
206 if (tc1->destructor != (talloc_destructor_t)-1) {
207 tc1->destructor = NULL;
209 _TLIST_REMOVE(tc2->refs, handle);
215 make a secondary reference to a pointer, hanging off the given context.
216 the pointer remains valid until both the original caller and this given
219 the major use for this is when two different structures need to reference the
220 same underlying data, and you want to be able to free the two instances separately,
223 void *talloc_reference(const void *context, const void *ptr)
225 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
226 struct talloc_reference_handle *handle;
227 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
228 if (handle == NULL) return NULL;
230 /* note that we hang the destructor off the handle, not the
231 main context as that allows the caller to still setup their
232 own destructor on the context if they want to */
233 talloc_set_destructor(handle, talloc_reference_destructor);
234 handle->ptr = discard_const_p(void, ptr);
235 _TLIST_ADD(tc->refs, handle);
240 remove a secondary reference to a pointer. This undo's what
241 talloc_reference() has done. The context and pointer arguments
242 must match those given to a talloc_reference()
244 static int talloc_unreference(const void *context, const void *ptr)
246 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
247 struct talloc_reference_handle *h;
249 if (context == NULL) {
250 context = null_context;
253 for (h=tc->refs;h;h=h->next) {
254 struct talloc_chunk *p = talloc_parent_chunk(h);
255 if ((p==NULL && context==NULL) || p+1 == context) break;
261 talloc_set_destructor(h, NULL);
262 _TLIST_REMOVE(tc->refs, h);
268 remove a specific parent context from a pointer. This is a more
269 controlled varient of talloc_free()
271 int talloc_unlink(const void *context, void *ptr)
273 struct talloc_chunk *tc_p, *new_p;
276 if (talloc_unreference(context, ptr) == 0) {
280 if (context == NULL) {
281 if (talloc_parent_chunk(ptr) != NULL) {
285 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
290 tc_p = talloc_chunk_from_ptr(ptr);
292 if (tc_p->refs == NULL) {
293 return talloc_free(ptr);
296 new_p = talloc_parent_chunk(tc_p->refs);
298 new_parent = new_p+1;
303 if (talloc_unreference(new_parent, ptr) != 0) {
307 talloc_steal(new_parent, ptr);
313 add a name to an existing pointer - va_list version
315 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
317 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
319 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
320 tc->name = talloc_vasprintf(ptr, fmt, ap);
322 talloc_set_name_const(tc->name, ".name");
327 add a name to an existing pointer
329 void talloc_set_name(const void *ptr, const char *fmt, ...)
333 talloc_set_name_v(ptr, fmt, ap);
338 more efficient way to add a name to a pointer - the name must point to a
341 void talloc_set_name_const(const void *ptr, const char *name)
343 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
348 create a named talloc pointer. Any talloc pointer can be named, and
349 talloc_named() operates just like talloc() except that it allows you
352 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
357 ptr = _talloc(context, size);
358 if (ptr == NULL) return NULL;
361 talloc_set_name_v(ptr, fmt, ap);
368 create a named talloc pointer. Any talloc pointer can be named, and
369 talloc_named() operates just like talloc() except that it allows you
372 void *talloc_named_const(const void *context, size_t size, const char *name)
376 ptr = _talloc(context, size);
381 talloc_set_name_const(ptr, name);
387 return the name of a talloc ptr, or "UNNAMED"
389 const char *talloc_get_name(const void *ptr)
391 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
392 if (tc->name == TALLOC_MAGIC_REFERENCE) {
402 this is for compatibility with older versions of talloc
404 void *talloc_init(const char *fmt, ...)
409 ptr = _talloc(NULL, 0);
410 if (ptr == NULL) return NULL;
413 talloc_set_name_v(ptr, fmt, ap);
421 free a talloc pointer. This also frees all child pointers of this
424 return 0 if the memory is actually freed, otherwise -1. The memory
425 will not be freed if the ref_count is > 1 or the destructor (if
426 any) returns non-zero
428 int talloc_free(void *ptr)
430 struct talloc_chunk *tc;
436 tc = talloc_chunk_from_ptr(ptr);
439 talloc_reference_destructor(tc->refs);
443 if (tc->destructor) {
444 talloc_destructor_t d = tc->destructor;
445 if (d == (talloc_destructor_t)-1) {
448 tc->destructor = (talloc_destructor_t)-1;
453 tc->destructor = NULL;
457 /* we need to work out who will own an abandoned child
458 if it cannot be freed. In priority order, the first
459 choice is owner of any remaining reference to this
460 pointer, the second choice is our parent, and the
461 final choice is the null context. */
462 void *child = tc->child+1;
463 const void *new_parent = null_context;
464 if (tc->child->refs) {
465 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
466 if (p) new_parent = p+1;
468 if (new_parent == null_context) {
469 struct talloc_chunk *p = talloc_parent_chunk(ptr);
470 if (p) new_parent = p+1;
472 talloc_free(talloc_steal(new_parent, child));
476 _TLIST_REMOVE(tc->parent->child, tc);
477 if (tc->parent->child) {
478 tc->parent->child->parent = tc->parent;
481 if (tc->prev) tc->prev->next = tc->next;
482 if (tc->next) tc->next->prev = tc->prev;
485 tc->magic = TALLOC_MAGIC_FREE;
494 A talloc version of realloc. The context argument is only used if
497 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
499 struct talloc_chunk *tc;
502 /* size zero is equivalent to free() */
508 if (size >= MAX_TALLOC_SIZE) {
512 /* realloc(NULL) is equavalent to malloc() */
514 return talloc_named_const(context, size, name);
517 tc = talloc_chunk_from_ptr(ptr);
519 /* don't allow realloc on referenced pointers */
524 /* by resetting magic we catch users of the old memory */
525 tc->magic = TALLOC_MAGIC_FREE;
527 new_ptr = realloc(tc, size + sizeof(*tc));
529 tc->magic = TALLOC_MAGIC;
534 tc->magic = TALLOC_MAGIC;
536 tc->parent->child = new_ptr;
547 talloc_set_name_const(tc+1, name);
549 return (void *)(tc+1);
553 move a lump of memory from one talloc context to another return the
554 ptr on success, or NULL if it could not be transferred
556 void *talloc_steal(const void *new_ctx, const void *ptr)
558 struct talloc_chunk *tc, *new_tc;
564 tc = talloc_chunk_from_ptr(ptr);
566 if (new_ctx == NULL) {
568 _TLIST_REMOVE(tc->parent->child, tc);
569 if (tc->parent->child) {
570 tc->parent->child->parent = tc->parent;
573 if (tc->prev) tc->prev->next = tc->next;
574 if (tc->next) tc->next->prev = tc->prev;
577 tc->parent = tc->next = tc->prev = NULL;
578 return discard_const_p(void, ptr);
581 new_tc = talloc_chunk_from_ptr(new_ctx);
584 return discard_const_p(void, ptr);
588 _TLIST_REMOVE(tc->parent->child, tc);
589 if (tc->parent->child) {
590 tc->parent->child->parent = tc->parent;
593 if (tc->prev) tc->prev->next = tc->next;
594 if (tc->next) tc->next->prev = tc->prev;
598 if (new_tc->child) new_tc->child->parent = NULL;
599 _TLIST_ADD(new_tc->child, tc);
601 return discard_const_p(void, ptr);
605 return the total size of a talloc pool (subtree)
607 off_t talloc_total_size(const void *ptr)
610 struct talloc_chunk *c, *tc;
619 tc = talloc_chunk_from_ptr(ptr);
622 for (c=tc->child;c;c=c->next) {
623 total += talloc_total_size(c+1);
629 return the total number of blocks in a talloc pool (subtree)
631 off_t talloc_total_blocks(const void *ptr)
634 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
637 for (c=tc->child;c;c=c->next) {
638 total += talloc_total_blocks(c+1);
644 return the number of external references to a pointer
646 static int talloc_reference_count(const void *ptr)
648 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
649 struct talloc_reference_handle *h;
652 for (h=tc->refs;h;h=h->next) {
659 report on memory usage by all children of a pointer, giving a full tree view
661 static void talloc_report_depth(const void *ptr, FILE *f, int depth)
663 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
665 for (c=tc->child;c;c=c->next) {
666 if (c->name == TALLOC_MAGIC_REFERENCE) {
667 struct talloc_reference_handle *handle = (void *)(c+1);
668 const char *name2 = talloc_get_name(handle->ptr);
669 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
671 const char *name = talloc_get_name(c+1);
672 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
675 (unsigned long)talloc_total_size(c+1),
676 (unsigned long)talloc_total_blocks(c+1),
677 talloc_reference_count(c+1));
678 talloc_report_depth(c+1, f, depth+1);
685 report on memory usage by all children of a pointer, giving a full tree view
687 void talloc_report_full(const void *ptr, FILE *f)
692 if (ptr == NULL) return;
694 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
695 talloc_get_name(ptr),
696 (unsigned long)talloc_total_size(ptr),
697 (unsigned long)talloc_total_blocks(ptr));
699 talloc_report_depth(ptr, f, 1);
703 report on memory usage by all children of a pointer
705 void talloc_report(const void *ptr, FILE *f)
707 struct talloc_chunk *c, *tc;
712 if (ptr == NULL) return;
714 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
715 talloc_get_name(ptr),
716 (unsigned long)talloc_total_size(ptr),
717 (unsigned long)talloc_total_blocks(ptr));
719 tc = talloc_chunk_from_ptr(ptr);
721 for (c=tc->child;c;c=c->next) {
722 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
723 talloc_get_name(c+1),
724 (unsigned long)talloc_total_size(c+1),
725 (unsigned long)talloc_total_blocks(c+1));
731 report on any memory hanging off the null context
733 static void talloc_report_null(void)
735 if (talloc_total_size(null_context) != 0) {
736 talloc_report(null_context, stderr);
741 report on any memory hanging off the null context
743 static void talloc_report_null_full(void)
745 if (talloc_total_size(null_context) != 0) {
746 talloc_report_full(null_context, stderr);
751 enable leak reporting on exit
753 void talloc_enable_leak_report(void)
755 null_context = talloc_named_const(NULL, 0, "null_context");
756 atexit(talloc_report_null);
760 enable full leak reporting on exit
762 void talloc_enable_leak_report_full(void)
764 null_context = talloc_named_const(NULL, 0, "null_context");
765 atexit(talloc_report_null_full);
769 talloc and zero memory.
771 void *talloc_zero(const void *ctx, size_t size)
773 void *p = talloc(ctx, size);
776 memset(p, '\0', size);
784 memdup with a talloc.
786 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
788 void *newp = talloc_named_const(t, size, name);
791 memcpy(newp, p, size);
800 char *talloc_strdup(const void *t, const char *p)
806 ret = talloc_memdup(t, p, strlen(p) + 1);
808 talloc_set_name_const(ret, ret);
814 strndup with a talloc
816 char *talloc_strndup(const void *t, const char *p, size_t n)
821 for (len=0; p[len] && len<n; len++) ;
823 ret = talloc(t, len + 1);
824 if (!ret) { return NULL; }
832 #define VA_COPY(dest, src) __va_copy(dest, src)
834 #define VA_COPY(dest, src) (dest) = (src)
838 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
846 len = vsnprintf(NULL, 0, fmt, ap2);
848 ret = talloc(t, len+1);
851 vsnprintf(ret, len+1, fmt, ap2);
852 talloc_set_name_const(ret, ret);
860 Perform string formatting, and return a pointer to newly allocated
861 memory holding the result, inside a memory pool.
863 char *talloc_asprintf(const void *t, const char *fmt, ...)
869 ret = talloc_vasprintf(t, fmt, ap);
876 * Realloc @p s to append the formatted result of @p fmt and @p ap,
877 * and return @p s, which may have moved. Good for gradually
878 * accumulating output into a string buffer.
881 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
883 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
895 len = vsnprintf(NULL, 0, fmt, ap2);
897 s = talloc_realloc(NULL, s, s_len + len+1);
902 vsnprintf(s+s_len, len+1, fmt, ap2);
903 talloc_set_name_const(s, s);
909 Realloc @p s to append the formatted result of @p fmt and return @p
910 s, which may have moved. Good for gradually accumulating output
911 into a string buffer.
913 char *talloc_asprintf_append(char *s, const char *fmt, ...)
918 s = talloc_vasprintf_append(s, fmt, ap);
924 alloc an array, checking for integer overflow in the array size
926 void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
928 if (count >= MAX_TALLOC_SIZE/el_size) {
931 return talloc_named_const(ctx, el_size * count, name);
936 realloc an array, checking for integer overflow in the array size
938 void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
940 if (count >= MAX_TALLOC_SIZE/el_size) {
943 ptr = talloc_realloc(ctx, ptr, el_size * count);
945 talloc_set_name_const(ptr, name);
951 a alloc function for ldb that uses talloc
953 void *talloc_ldb_alloc(void *context, void *ptr, size_t size)
956 return talloc(context, size);
962 return talloc_realloc(context, ptr, size);