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/
29 #if defined(HAVE_CONFIG_H)
33 #define HAVE_SYS_TYPES_H
46 #define TALLOC_ABORT(reason) do{ \
47 fprintf(stderr, "%s: name: %s\n", __func__, tc->name); \
48 assert(0 && reason);} while (0)
51 #ifdef HAVE_SYS_TYPES_H
52 #include <sys/types.h>
71 /* use this to force every realloc to change the pointer, to stress test
72 code that might not cope */
73 #define ALWAYS_REALLOC 0
76 #define MAX_TALLOC_SIZE 0x10000000
77 #define TALLOC_MAGIC 0xe814ec4f
78 #define TALLOC_MAGIC_FREE 0x7faebef3
79 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
81 /* by default we abort when given a bad pointer (such as when talloc_free() is
82 * called on a pointer that came from malloc() */
84 #define TALLOC_ABORT(reason) abort()
87 #ifndef discard_const_p
88 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
89 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
91 # define discard_const_p(type, ptr) ((type *)(ptr))
95 /* this null_context is only used if talloc_enable_leak_report() or
96 talloc_enable_leak_report_full() is called, otherwise it remains
99 static const void *null_context;
100 static void *cleanup_context;
103 struct talloc_reference_handle {
104 struct talloc_reference_handle *next, *prev;
108 typedef int (*talloc_destructor_t)(void *);
110 struct talloc_chunk {
111 struct talloc_chunk *next, *prev;
112 struct talloc_chunk *parent, *child;
113 struct talloc_reference_handle *refs;
115 talloc_destructor_t destructor;
123 /* panic if we get a bad magic value */
124 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
126 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
127 if (tc->u.magic != TALLOC_MAGIC) {
128 if (tc->u.magic == TALLOC_MAGIC_FREE) {
129 TALLOC_ABORT("Bad talloc magic value - double free");
131 TALLOC_ABORT("Bad talloc magic value - unknown value");
138 /* hook into the front of the list */
139 #define _TLIST_ADD(list, p) \
143 (p)->next = (p)->prev = NULL; \
145 (list)->prev = (p); \
146 (p)->next = (list); \
152 /* remove an element from a list - element doesn't have to be in list. */
153 #define _TLIST_REMOVE(list, p) \
155 if ((p) == (list)) { \
156 (list) = (p)->next; \
157 if (list) (list)->prev = NULL; \
159 if ((p)->prev) (p)->prev->next = (p)->next; \
160 if ((p)->next) (p)->next->prev = (p)->prev; \
162 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
167 return the parent chunk of a pointer
169 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
171 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
172 while (tc->prev) tc=tc->prev;
176 void *talloc_parent(const void *ptr)
178 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
179 return (void *)(tc+1);
183 Allocate a bit of memory as a child of an existing pointer
185 void *_talloc(const void *context, size_t size)
187 struct talloc_chunk *tc;
189 if (context == NULL) {
190 context = null_context;
193 if (size >= MAX_TALLOC_SIZE) {
197 tc = malloc(sizeof(*tc)+size);
198 if (tc == NULL) return NULL;
201 tc->u.magic = TALLOC_MAGIC;
202 tc->destructor = NULL;
208 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
213 parent->child->parent = NULL;
216 _TLIST_ADD(parent->child, tc);
218 tc->next = tc->prev = tc->parent = NULL;
221 return (void *)(tc+1);
226 setup a destructor to be called on free of a pointer
227 the destructor should return 0 on success, or -1 on failure.
228 if the destructor fails then the free is failed, and the memory can
229 be continued to be used
231 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
233 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
234 tc->destructor = destructor;
238 increase the reference count on a piece of memory.
240 void talloc_increase_ref_count(const void *ptr)
242 talloc_reference(null_context, ptr);
246 helper for talloc_reference()
248 static int talloc_reference_destructor(void *ptr)
250 struct talloc_reference_handle *handle = ptr;
251 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
252 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
253 if (tc1->destructor != (talloc_destructor_t)-1) {
254 tc1->destructor = NULL;
256 _TLIST_REMOVE(tc2->refs, handle);
262 make a secondary reference to a pointer, hanging off the given context.
263 the pointer remains valid until both the original caller and this given
266 the major use for this is when two different structures need to reference the
267 same underlying data, and you want to be able to free the two instances
268 separately, and in either order
270 void *talloc_reference(const void *context, const void *ptr)
272 struct talloc_chunk *tc;
273 struct talloc_reference_handle *handle;
274 if (ptr == NULL) return NULL;
276 tc = talloc_chunk_from_ptr(ptr);
277 handle = talloc_named_const(context, sizeof(*handle),
278 TALLOC_MAGIC_REFERENCE);
280 if (handle == NULL) return NULL;
282 /* note that we hang the destructor off the handle, not the
283 main context as that allows the caller to still setup their
284 own destructor on the context if they want to */
285 talloc_set_destructor(handle, talloc_reference_destructor);
286 handle->ptr = discard_const_p(void, ptr);
287 _TLIST_ADD(tc->refs, handle);
292 remove a secondary reference to a pointer. This undo's what
293 talloc_reference() has done. The context and pointer arguments
294 must match those given to a talloc_reference()
296 static int talloc_unreference(const void *context, const void *ptr)
298 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
299 struct talloc_reference_handle *h;
301 if (context == NULL) {
302 context = null_context;
305 for (h=tc->refs;h;h=h->next) {
306 struct talloc_chunk *p = talloc_parent_chunk(h);
307 if ((p==NULL && context==NULL) || p+1 == context) break;
313 talloc_set_destructor(h, NULL);
314 _TLIST_REMOVE(tc->refs, h);
320 remove a specific parent context from a pointer. This is a more
321 controlled varient of talloc_free()
323 int talloc_unlink(const void *context, void *ptr)
325 struct talloc_chunk *tc_p, *new_p;
332 if (context == NULL) {
333 context = null_context;
336 if (talloc_unreference(context, ptr) == 0) {
340 if (context == NULL) {
341 if (talloc_parent_chunk(ptr) != NULL) {
345 if (talloc_chunk_from_ptr(context)
346 != talloc_parent_chunk(ptr)) {
351 tc_p = talloc_chunk_from_ptr(ptr);
353 if (tc_p->refs == NULL) {
354 return talloc_free(ptr);
357 new_p = talloc_parent_chunk(tc_p->refs);
359 new_parent = new_p+1;
364 if (talloc_unreference(new_parent, ptr) != 0) {
368 talloc_steal(new_parent, ptr);
374 add a name to an existing pointer - va_list version
376 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
377 PRINTF_ATTRIBUTE(2,0);
379 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
381 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
382 tc->name = talloc_vasprintf(ptr, fmt, ap);
384 talloc_set_name_const(tc->name, ".name");
389 add a name to an existing pointer
391 void talloc_set_name(const void *ptr, const char *fmt, ...)
395 talloc_set_name_v(ptr, fmt, ap);
400 more efficient way to add a name to a pointer - the name must point to a
403 void talloc_set_name_const(const void *ptr, const char *name)
405 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
410 create a named talloc pointer. Any talloc pointer can be named, and
411 talloc_named() operates just like talloc() except that it allows you
414 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
419 ptr = _talloc(context, size);
420 if (ptr == NULL) return NULL;
423 talloc_set_name_v(ptr, fmt, ap);
430 create a named talloc pointer. Any talloc pointer can be named, and
431 talloc_named() operates just like talloc() except that it allows you
434 void *talloc_named_const(const void *context, size_t size, const char *name)
438 ptr = _talloc(context, size);
443 talloc_set_name_const(ptr, name);
449 return the name of a talloc ptr, or "UNNAMED"
451 const char *talloc_get_name(const void *ptr)
453 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
454 if (tc->name == TALLOC_MAGIC_REFERENCE) {
465 check if a pointer has the given name. If it does, return the pointer,
466 otherwise return NULL
468 void *talloc_check_name(const void *ptr, const char *name)
471 if (ptr == NULL) return NULL;
472 pname = talloc_get_name(ptr);
473 if (pname == name || strcmp(pname, name) == 0) {
474 return discard_const_p(void, ptr);
481 this is for compatibility with older versions of talloc
483 void *talloc_init(const char *fmt, ...)
488 ptr = _talloc(NULL, 0);
489 if (ptr == NULL) return NULL;
492 talloc_set_name_v(ptr, fmt, ap);
499 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
500 should probably not be used in new code. It's in here to keep the talloc
501 code consistent across Samba 3 and 4.
503 static void talloc_free_children(void *ptr)
505 struct talloc_chunk *tc;
511 tc = talloc_chunk_from_ptr(ptr);
514 /* we need to work out who will own an abandoned child
515 if it cannot be freed. In priority order, the first
516 choice is owner of any remaining reference to this
517 pointer, the second choice is our parent, and the
518 final choice is the null context. */
519 void *child = tc->child+1;
520 const void *new_parent = null_context;
521 if (tc->child->refs) {
522 struct talloc_chunk *p =
523 talloc_parent_chunk(tc->child->refs);
524 if (p) new_parent = p+1;
526 if (talloc_free(child) == -1) {
527 if (new_parent == null_context) {
528 struct talloc_chunk *p =
529 talloc_parent_chunk(ptr);
530 if (p) new_parent = p+1;
532 talloc_steal(new_parent, child);
538 free a talloc pointer. This also frees all child pointers of this
541 return 0 if the memory is actually freed, otherwise -1. The memory
542 will not be freed if the ref_count is > 1 or the destructor (if
543 any) returns non-zero
545 int talloc_free(void *ptr)
547 struct talloc_chunk *tc;
553 tc = talloc_chunk_from_ptr(ptr);
556 talloc_reference_destructor(tc->refs);
560 if (tc->destructor) {
561 talloc_destructor_t d = tc->destructor;
562 if (d == (talloc_destructor_t)-1) {
565 tc->destructor = (talloc_destructor_t)-1;
570 tc->destructor = NULL;
573 talloc_free_children(ptr);
576 _TLIST_REMOVE(tc->parent->child, tc);
577 if (tc->parent->child) {
578 tc->parent->child->parent = tc->parent;
581 if (tc->prev) tc->prev->next = tc->next;
582 if (tc->next) tc->next->prev = tc->prev;
585 tc->u.magic = TALLOC_MAGIC_FREE;
594 A talloc version of realloc. The context argument is only used if
597 void *_talloc_realloc(const void *context, void *ptr, size_t size,
600 struct talloc_chunk *tc;
603 /* size zero is equivalent to free() */
609 if (size >= MAX_TALLOC_SIZE) {
613 /* realloc(NULL) is equavalent to malloc() */
615 return talloc_named_const(context, size, name);
618 tc = talloc_chunk_from_ptr(ptr);
620 /* don't allow realloc on referenced pointers */
625 /* by resetting magic we catch users of the old memory */
626 tc->u.magic = TALLOC_MAGIC_FREE;
629 new_ptr = malloc(size + sizeof(*tc));
631 memcpy(new_ptr, tc, tc->size + sizeof(*tc));
635 new_ptr = realloc(tc, size + sizeof(*tc));
638 tc->u.magic = TALLOC_MAGIC;
643 tc->u.magic = TALLOC_MAGIC;
645 tc->parent->child = new_ptr;
648 tc->child->parent = new_ptr;
659 talloc_set_name_const(tc+1, name);
661 return (void *)(tc+1);
665 move a lump of memory from one talloc context to another return the
666 ptr on success, or NULL if it could not be transferred.
667 passing NULL as ptr will always return NULL with no side effects.
669 void *talloc_steal(const void *new_ctx, const void *ptr)
671 struct talloc_chunk *tc, *new_tc;
677 if (new_ctx == NULL) {
678 new_ctx = null_context;
681 tc = talloc_chunk_from_ptr(ptr);
683 if (new_ctx == NULL) {
685 _TLIST_REMOVE(tc->parent->child, tc);
686 if (tc->parent->child) {
687 tc->parent->child->parent = tc->parent;
690 if (tc->prev) tc->prev->next = tc->next;
691 if (tc->next) tc->next->prev = tc->prev;
694 tc->parent = tc->next = tc->prev = NULL;
695 return discard_const_p(void, ptr);
698 new_tc = talloc_chunk_from_ptr(new_ctx);
701 return discard_const_p(void, ptr);
705 _TLIST_REMOVE(tc->parent->child, tc);
706 if (tc->parent->child) {
707 tc->parent->child->parent = tc->parent;
710 if (tc->prev) tc->prev->next = tc->next;
711 if (tc->next) tc->next->prev = tc->prev;
715 if (new_tc->child) new_tc->child->parent = NULL;
716 _TLIST_ADD(new_tc->child, tc);
718 return discard_const_p(void, ptr);
722 return the total size of a talloc pool (subtree)
724 off_t talloc_total_size(const void *ptr)
727 struct talloc_chunk *c, *tc;
736 tc = talloc_chunk_from_ptr(ptr);
739 for (c=tc->child;c;c=c->next) {
740 total += talloc_total_size(c+1);
746 return the total number of blocks in a talloc pool (subtree)
748 off_t talloc_total_blocks(const void *ptr)
751 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
754 for (c=tc->child;c;c=c->next) {
755 total += talloc_total_blocks(c+1);
761 return the number of external references to a pointer
763 static int talloc_reference_count(const void *ptr)
765 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
766 struct talloc_reference_handle *h;
769 for (h=tc->refs;h;h=h->next) {
776 report on memory usage by all children of a pointer, giving a full tree view
778 void talloc_report_depth(const void *ptr, FILE *f, int depth)
780 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
782 for (c=tc->child;c;c=c->next) {
783 if (c->name == TALLOC_MAGIC_REFERENCE) {
784 struct talloc_reference_handle *handle = (void *)(c+1);
785 const char *name2 = talloc_get_name(handle->ptr);
786 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
788 const char *name = talloc_get_name(c+1);
789 fprintf(f, "%*s%-30s contains %6lu bytes "
790 "in %3lu blocks (ref %d)\n",
792 (unsigned long)talloc_total_size(c+1),
793 (unsigned long)talloc_total_blocks(c+1),
794 talloc_reference_count(c+1));
795 talloc_report_depth(c+1, f, depth+1);
802 report on memory usage by all children of a pointer, giving a full tree view
804 void talloc_report_full(const void *ptr, FILE *f)
809 if (ptr == NULL) return;
811 fprintf(f, "full talloc report on '%s' "
812 "(total %lu bytes in %lu blocks)\n",
813 talloc_get_name(ptr),
814 (unsigned long)talloc_total_size(ptr),
815 (unsigned long)talloc_total_blocks(ptr));
817 talloc_report_depth(ptr, f, 1);
822 report on memory usage by all children of a pointer
824 void talloc_report(const void *ptr, FILE *f)
826 struct talloc_chunk *c, *tc;
831 if (ptr == NULL) return;
833 fprintf(f, "talloc report on '%s' (total %lu bytes in %lu blocks)\n",
834 talloc_get_name(ptr),
835 (unsigned long)talloc_total_size(ptr),
836 (unsigned long)talloc_total_blocks(ptr));
838 tc = talloc_chunk_from_ptr(ptr);
840 for (c=tc->child;c;c=c->next) {
841 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
842 talloc_get_name(c+1),
843 (unsigned long)talloc_total_size(c+1),
844 (unsigned long)talloc_total_blocks(c+1));
850 report on any memory hanging off the null context
852 static void talloc_report_null(void)
854 if (talloc_total_size(null_context) != 0) {
855 talloc_report(null_context, stderr);
860 report on any memory hanging off the null context
862 static void talloc_report_null_full(void)
864 if (talloc_total_size(null_context) != 0) {
865 talloc_report_full(null_context, stderr);
870 enable tracking of the NULL context
872 void talloc_enable_null_tracking(void)
874 if (null_context == NULL) {
875 null_context = talloc_named_const(NULL, 0, "null_context");
880 enable leak reporting on exit
882 void talloc_enable_leak_report(void)
884 talloc_enable_null_tracking();
885 atexit(talloc_report_null);
889 enable full leak reporting on exit
891 void talloc_enable_leak_report_full(void)
893 talloc_enable_null_tracking();
894 atexit(talloc_report_null_full);
898 talloc and zero memory.
900 void *_talloc_zero(const void *ctx, size_t size, const char *name)
902 void *p = talloc_named_const(ctx, size, name);
905 memset(p, '\0', size);
913 memdup with a talloc.
915 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
917 void *newp = talloc_named_const(t, size, name);
920 memcpy(newp, p, size);
929 char *talloc_strdup(const void *t, const char *p)
935 ret = talloc_memdup(t, p, strlen(p) + 1);
937 talloc_set_name_const(ret, ret);
943 strndup with a talloc
945 char *talloc_strndup(const void *t, const char *p, size_t n)
950 for (len=0; len<n && p[len]; len++) ;
952 ret = _talloc(t, len + 1);
953 if (!ret) { return NULL; }
956 talloc_set_name_const(ret, ret);
962 #define VA_COPY(dest, src) va_copy(dest, src)
963 #elif defined(HAVE___VA_COPY)
964 #define VA_COPY(dest, src) __va_copy(dest, src)
966 #define VA_COPY(dest, src) (dest) = (src)
970 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
978 len = vsnprintf(NULL, 0, fmt, ap2);
980 ret = _talloc(t, len+1);
983 vsnprintf(ret, len+1, fmt, ap2);
984 talloc_set_name_const(ret, ret);
992 Perform string formatting, and return a pointer to newly allocated
993 memory holding the result, inside a memory pool.
995 char *talloc_asprintf(const void *t, const char *fmt, ...)
1001 ret = talloc_vasprintf(t, fmt, ap);
1008 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1009 * and return @p s, which may have moved. Good for gradually
1010 * accumulating output into a string buffer.
1013 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1014 PRINTF_ATTRIBUTE(2,0);
1016 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1018 struct talloc_chunk *tc;
1023 return talloc_vasprintf(NULL, fmt, ap);
1026 tc = talloc_chunk_from_ptr(s);
1030 s_len = tc->size - 1;
1031 len = vsnprintf(NULL, 0, fmt, ap2);
1033 s = talloc_realloc(NULL, s, char, s_len + len+1);
1034 if (!s) return NULL;
1038 vsnprintf(s+s_len, len+1, fmt, ap2);
1039 talloc_set_name_const(s, s);
1045 Realloc @p s to append the formatted result of @p fmt and return @p
1046 s, which may have moved. Good for gradually accumulating output
1047 into a string buffer.
1049 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1054 s = talloc_vasprintf_append(s, fmt, ap);
1060 alloc an array, checking for integer overflow in the array size
1062 void *_talloc_array(const void *ctx, size_t el_size, unsigned count,
1065 if (count >= MAX_TALLOC_SIZE/el_size) {
1068 return talloc_named_const(ctx, el_size * count, name);
1072 alloc an zero array, checking for integer overflow in the array size
1074 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count,
1077 if (count >= MAX_TALLOC_SIZE/el_size) {
1080 return _talloc_zero(ctx, el_size * count, name);
1085 realloc an array, checking for integer overflow in the array size
1087 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size,
1088 unsigned count, const char *name)
1090 if (count >= MAX_TALLOC_SIZE/el_size) {
1093 return _talloc_realloc(ctx, ptr, el_size * count, name);
1097 a function version of talloc_realloc(), so it can be passed as a function
1098 pointer to libraries that want a realloc function (a realloc function
1099 encapsulates all the basic capabilities of an allocation library, which is
1102 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1104 return _talloc_realloc(context, ptr, size, NULL);
1108 static void talloc_autofree(void)
1110 talloc_free(cleanup_context);
1111 cleanup_context = NULL;
1115 return a context which will be auto-freed on exit
1116 this is useful for reducing the noise in leak reports
1118 void *talloc_autofree_context(void)
1120 if (cleanup_context == NULL) {
1121 cleanup_context = talloc_named_const(NULL, 0,
1122 "autofree_context");
1123 atexit(talloc_autofree);
1125 return cleanup_context;
1128 size_t talloc_get_size(const void *context)
1130 struct talloc_chunk *tc;
1132 if (context == NULL)
1135 tc = talloc_chunk_from_ptr(context);