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
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>
64 /* use this to force every realloc to change the pointer, to stress test
65 code that might not cope */
66 #define ALWAYS_REALLOC 0
69 #define MAX_TALLOC_SIZE 0x10000000
70 #define TALLOC_MAGIC 0xe814ec4f
71 #define TALLOC_MAGIC_FREE 0x7faebef3
72 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
74 /* by default we abort when given a bad pointer (such as when talloc_free() is
75 * called on a pointer that came from malloc() */
77 #define TALLOC_ABORT(reason) abort()
80 #ifndef discard_const_p
81 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
82 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
84 # define discard_const_p(type, ptr) ((type *)(ptr))
88 /* this null_context is only used if talloc_enable_leak_report() or
89 talloc_enable_leak_report_full() is called, otherwise it remains
92 static const void *null_context;
93 static void *cleanup_context;
96 struct talloc_reference_handle {
97 struct talloc_reference_handle *next, *prev;
101 typedef int (*talloc_destructor_t)(void *);
103 struct talloc_chunk {
104 struct talloc_chunk *next, *prev;
105 struct talloc_chunk *parent, *child;
106 struct talloc_reference_handle *refs;
108 talloc_destructor_t destructor;
116 /* panic if we get a bad magic value */
117 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
119 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
120 if (tc->u.magic != TALLOC_MAGIC) {
121 if (tc->u.magic == TALLOC_MAGIC_FREE) {
122 TALLOC_ABORT("Bad talloc magic value - double free");
124 TALLOC_ABORT("Bad talloc magic value - unknown value");
131 /* hook into the front of the list */
132 #define _TLIST_ADD(list, p) \
136 (p)->next = (p)->prev = NULL; \
138 (list)->prev = (p); \
139 (p)->next = (list); \
145 /* remove an element from a list - element doesn't have to be in list. */
146 #define _TLIST_REMOVE(list, p) \
148 if ((p) == (list)) { \
149 (list) = (p)->next; \
150 if (list) (list)->prev = NULL; \
152 if ((p)->prev) (p)->prev->next = (p)->next; \
153 if ((p)->next) (p)->next->prev = (p)->prev; \
155 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
160 return the parent chunk of a pointer
162 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
164 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
165 while (tc->prev) tc=tc->prev;
169 void *talloc_parent(const void *ptr)
171 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
172 return (void *)(tc+1);
176 Allocate a bit of memory as a child of an existing pointer
178 void *_talloc(const void *context, size_t size)
180 struct talloc_chunk *tc;
182 if (context == NULL) {
183 context = null_context;
186 if (size >= MAX_TALLOC_SIZE) {
190 tc = malloc(sizeof(*tc)+size);
191 if (tc == NULL) return NULL;
194 tc->u.magic = TALLOC_MAGIC;
195 tc->destructor = NULL;
201 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
206 parent->child->parent = NULL;
209 _TLIST_ADD(parent->child, tc);
211 tc->next = tc->prev = tc->parent = NULL;
214 return (void *)(tc+1);
219 setup a destructor to be called on free of a pointer
220 the destructor should return 0 on success, or -1 on failure.
221 if the destructor fails then the free is failed, and the memory can
222 be continued to be used
224 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
226 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
227 tc->destructor = destructor;
231 increase the reference count on a piece of memory.
233 void talloc_increase_ref_count(const void *ptr)
235 talloc_reference(null_context, ptr);
239 helper for talloc_reference()
241 static int talloc_reference_destructor(void *ptr)
243 struct talloc_reference_handle *handle = ptr;
244 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
245 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
246 if (tc1->destructor != (talloc_destructor_t)-1) {
247 tc1->destructor = NULL;
249 _TLIST_REMOVE(tc2->refs, handle);
255 make a secondary reference to a pointer, hanging off the given context.
256 the pointer remains valid until both the original caller and this given
259 the major use for this is when two different structures need to reference the
260 same underlying data, and you want to be able to free the two instances
261 separately, and in either order
263 void *talloc_reference(const void *context, const void *ptr)
265 struct talloc_chunk *tc;
266 struct talloc_reference_handle *handle;
267 if (ptr == NULL) return NULL;
269 tc = talloc_chunk_from_ptr(ptr);
270 handle = talloc_named_const(context, sizeof(*handle),
271 TALLOC_MAGIC_REFERENCE);
273 if (handle == NULL) return NULL;
275 /* note that we hang the destructor off the handle, not the
276 main context as that allows the caller to still setup their
277 own destructor on the context if they want to */
278 talloc_set_destructor(handle, talloc_reference_destructor);
279 handle->ptr = discard_const_p(void, ptr);
280 _TLIST_ADD(tc->refs, handle);
285 remove a secondary reference to a pointer. This undo's what
286 talloc_reference() has done. The context and pointer arguments
287 must match those given to a talloc_reference()
289 static int talloc_unreference(const void *context, const void *ptr)
291 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
292 struct talloc_reference_handle *h;
294 if (context == NULL) {
295 context = null_context;
298 for (h=tc->refs;h;h=h->next) {
299 struct talloc_chunk *p = talloc_parent_chunk(h);
300 if ((p==NULL && context==NULL) || p+1 == context) break;
306 talloc_set_destructor(h, NULL);
307 _TLIST_REMOVE(tc->refs, h);
313 remove a specific parent context from a pointer. This is a more
314 controlled varient of talloc_free()
316 int talloc_unlink(const void *context, void *ptr)
318 struct talloc_chunk *tc_p, *new_p;
325 if (context == NULL) {
326 context = null_context;
329 if (talloc_unreference(context, ptr) == 0) {
333 if (context == NULL) {
334 if (talloc_parent_chunk(ptr) != NULL) {
338 if (talloc_chunk_from_ptr(context)
339 != talloc_parent_chunk(ptr)) {
344 tc_p = talloc_chunk_from_ptr(ptr);
346 if (tc_p->refs == NULL) {
347 return talloc_free(ptr);
350 new_p = talloc_parent_chunk(tc_p->refs);
352 new_parent = new_p+1;
357 if (talloc_unreference(new_parent, ptr) != 0) {
361 talloc_steal(new_parent, ptr);
367 add a name to an existing pointer - va_list version
369 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
370 PRINTF_ATTRIBUTE(2,0);
372 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
374 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
375 tc->name = talloc_vasprintf(ptr, fmt, ap);
377 talloc_set_name_const(tc->name, ".name");
382 add a name to an existing pointer
384 void talloc_set_name(const void *ptr, const char *fmt, ...)
388 talloc_set_name_v(ptr, fmt, ap);
393 more efficient way to add a name to a pointer - the name must point to a
396 void talloc_set_name_const(const void *ptr, const char *name)
398 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
403 create a named talloc pointer. Any talloc pointer can be named, and
404 talloc_named() operates just like talloc() except that it allows you
407 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
412 ptr = _talloc(context, size);
413 if (ptr == NULL) return NULL;
416 talloc_set_name_v(ptr, fmt, ap);
423 create a named talloc pointer. Any talloc pointer can be named, and
424 talloc_named() operates just like talloc() except that it allows you
427 void *talloc_named_const(const void *context, size_t size, const char *name)
431 ptr = _talloc(context, size);
436 talloc_set_name_const(ptr, name);
442 return the name of a talloc ptr, or "UNNAMED"
444 const char *talloc_get_name(const void *ptr)
446 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
447 if (tc->name == TALLOC_MAGIC_REFERENCE) {
458 check if a pointer has the given name. If it does, return the pointer,
459 otherwise return NULL
461 void *talloc_check_name(const void *ptr, const char *name)
464 if (ptr == NULL) return NULL;
465 pname = talloc_get_name(ptr);
466 if (pname == name || strcmp(pname, name) == 0) {
467 return discard_const_p(void, ptr);
474 this is for compatibility with older versions of talloc
476 void *talloc_init(const char *fmt, ...)
481 ptr = _talloc(NULL, 0);
482 if (ptr == NULL) return NULL;
485 talloc_set_name_v(ptr, fmt, ap);
492 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
493 should probably not be used in new code. It's in here to keep the talloc
494 code consistent across Samba 3 and 4.
496 static void talloc_free_children(void *ptr)
498 struct talloc_chunk *tc;
504 tc = talloc_chunk_from_ptr(ptr);
507 /* we need to work out who will own an abandoned child
508 if it cannot be freed. In priority order, the first
509 choice is owner of any remaining reference to this
510 pointer, the second choice is our parent, and the
511 final choice is the null context. */
512 void *child = tc->child+1;
513 const void *new_parent = null_context;
514 if (tc->child->refs) {
515 struct talloc_chunk *p =
516 talloc_parent_chunk(tc->child->refs);
517 if (p) new_parent = p+1;
519 if (talloc_free(child) == -1) {
520 if (new_parent == null_context) {
521 struct talloc_chunk *p =
522 talloc_parent_chunk(ptr);
523 if (p) new_parent = p+1;
525 talloc_steal(new_parent, child);
531 free a talloc pointer. This also frees all child pointers of this
534 return 0 if the memory is actually freed, otherwise -1. The memory
535 will not be freed if the ref_count is > 1 or the destructor (if
536 any) returns non-zero
538 int talloc_free(void *ptr)
540 struct talloc_chunk *tc;
546 tc = talloc_chunk_from_ptr(ptr);
549 talloc_reference_destructor(tc->refs);
553 if (tc->destructor) {
554 talloc_destructor_t d = tc->destructor;
555 if (d == (talloc_destructor_t)-1) {
558 tc->destructor = (talloc_destructor_t)-1;
563 tc->destructor = NULL;
566 talloc_free_children(ptr);
569 _TLIST_REMOVE(tc->parent->child, tc);
570 if (tc->parent->child) {
571 tc->parent->child->parent = tc->parent;
574 if (tc->prev) tc->prev->next = tc->next;
575 if (tc->next) tc->next->prev = tc->prev;
578 tc->u.magic = TALLOC_MAGIC_FREE;
587 A talloc version of realloc. The context argument is only used if
590 void *_talloc_realloc(const void *context, void *ptr, size_t size,
593 struct talloc_chunk *tc;
596 /* size zero is equivalent to free() */
602 if (size >= MAX_TALLOC_SIZE) {
606 /* realloc(NULL) is equavalent to malloc() */
608 return talloc_named_const(context, size, name);
611 tc = talloc_chunk_from_ptr(ptr);
613 /* don't allow realloc on referenced pointers */
618 /* by resetting magic we catch users of the old memory */
619 tc->u.magic = TALLOC_MAGIC_FREE;
622 new_ptr = malloc(size + sizeof(*tc));
624 memcpy(new_ptr, tc, tc->size + sizeof(*tc));
628 new_ptr = realloc(tc, size + sizeof(*tc));
631 tc->u.magic = TALLOC_MAGIC;
636 tc->u.magic = TALLOC_MAGIC;
638 tc->parent->child = new_ptr;
641 tc->child->parent = new_ptr;
652 talloc_set_name_const(tc+1, name);
654 return (void *)(tc+1);
658 move a lump of memory from one talloc context to another return the
659 ptr on success, or NULL if it could not be transferred.
660 passing NULL as ptr will always return NULL with no side effects.
662 void *talloc_steal(const void *new_ctx, const void *ptr)
664 struct talloc_chunk *tc, *new_tc;
670 if (new_ctx == NULL) {
671 new_ctx = null_context;
674 tc = talloc_chunk_from_ptr(ptr);
676 if (new_ctx == NULL) {
678 _TLIST_REMOVE(tc->parent->child, tc);
679 if (tc->parent->child) {
680 tc->parent->child->parent = tc->parent;
683 if (tc->prev) tc->prev->next = tc->next;
684 if (tc->next) tc->next->prev = tc->prev;
687 tc->parent = tc->next = tc->prev = NULL;
688 return discard_const_p(void, ptr);
691 new_tc = talloc_chunk_from_ptr(new_ctx);
694 return discard_const_p(void, ptr);
698 _TLIST_REMOVE(tc->parent->child, tc);
699 if (tc->parent->child) {
700 tc->parent->child->parent = tc->parent;
703 if (tc->prev) tc->prev->next = tc->next;
704 if (tc->next) tc->next->prev = tc->prev;
708 if (new_tc->child) new_tc->child->parent = NULL;
709 _TLIST_ADD(new_tc->child, tc);
711 return discard_const_p(void, ptr);
715 return the total size of a talloc pool (subtree)
717 off_t talloc_total_size(const void *ptr)
720 struct talloc_chunk *c, *tc;
729 tc = talloc_chunk_from_ptr(ptr);
732 for (c=tc->child;c;c=c->next) {
733 total += talloc_total_size(c+1);
739 return the total number of blocks in a talloc pool (subtree)
741 off_t talloc_total_blocks(const void *ptr)
744 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
747 for (c=tc->child;c;c=c->next) {
748 total += talloc_total_blocks(c+1);
754 return the number of external references to a pointer
756 static int talloc_reference_count(const void *ptr)
758 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
759 struct talloc_reference_handle *h;
762 for (h=tc->refs;h;h=h->next) {
769 report on memory usage by all children of a pointer, giving a full tree view
771 void talloc_report_depth(const void *ptr, FILE *f, int depth)
773 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
775 for (c=tc->child;c;c=c->next) {
776 if (c->name == TALLOC_MAGIC_REFERENCE) {
777 struct talloc_reference_handle *handle = (void *)(c+1);
778 const char *name2 = talloc_get_name(handle->ptr);
779 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
781 const char *name = talloc_get_name(c+1);
782 fprintf(f, "%*s%-30s contains %6lu bytes "
783 "in %3lu blocks (ref %d)\n",
785 (unsigned long)talloc_total_size(c+1),
786 (unsigned long)talloc_total_blocks(c+1),
787 talloc_reference_count(c+1));
788 talloc_report_depth(c+1, f, depth+1);
795 report on memory usage by all children of a pointer, giving a full tree view
797 void talloc_report_full(const void *ptr, FILE *f)
802 if (ptr == NULL) return;
804 fprintf(f, "full talloc report on '%s' "
805 "(total %lu bytes in %lu blocks)\n",
806 talloc_get_name(ptr),
807 (unsigned long)talloc_total_size(ptr),
808 (unsigned long)talloc_total_blocks(ptr));
810 talloc_report_depth(ptr, f, 1);
815 report on memory usage by all children of a pointer
817 void talloc_report(const void *ptr, FILE *f)
819 struct talloc_chunk *c, *tc;
824 if (ptr == NULL) return;
826 fprintf(f, "talloc report on '%s' (total %lu bytes in %lu blocks)\n",
827 talloc_get_name(ptr),
828 (unsigned long)talloc_total_size(ptr),
829 (unsigned long)talloc_total_blocks(ptr));
831 tc = talloc_chunk_from_ptr(ptr);
833 for (c=tc->child;c;c=c->next) {
834 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
835 talloc_get_name(c+1),
836 (unsigned long)talloc_total_size(c+1),
837 (unsigned long)talloc_total_blocks(c+1));
843 report on any memory hanging off the null context
845 static void talloc_report_null(void)
847 if (talloc_total_size(null_context) != 0) {
848 talloc_report(null_context, stderr);
853 report on any memory hanging off the null context
855 static void talloc_report_null_full(void)
857 if (talloc_total_size(null_context) != 0) {
858 talloc_report_full(null_context, stderr);
863 enable tracking of the NULL context
865 void talloc_enable_null_tracking(void)
867 if (null_context == NULL) {
868 null_context = talloc_named_const(NULL, 0, "null_context");
873 enable leak reporting on exit
875 void talloc_enable_leak_report(void)
877 talloc_enable_null_tracking();
878 atexit(talloc_report_null);
882 enable full leak reporting on exit
884 void talloc_enable_leak_report_full(void)
886 talloc_enable_null_tracking();
887 atexit(talloc_report_null_full);
891 talloc and zero memory.
893 void *_talloc_zero(const void *ctx, size_t size, const char *name)
895 void *p = talloc_named_const(ctx, size, name);
898 memset(p, '\0', size);
906 memdup with a talloc.
908 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
910 void *newp = talloc_named_const(t, size, name);
913 memcpy(newp, p, size);
922 char *talloc_strdup(const void *t, const char *p)
928 ret = talloc_memdup(t, p, strlen(p) + 1);
930 talloc_set_name_const(ret, ret);
936 strndup with a talloc
938 char *talloc_strndup(const void *t, const char *p, size_t n)
943 for (len=0; len<n && p[len]; len++) ;
945 ret = _talloc(t, len + 1);
946 if (!ret) { return NULL; }
949 talloc_set_name_const(ret, ret);
955 #define VA_COPY(dest, src) va_copy(dest, src)
956 #elif defined(HAVE___VA_COPY)
957 #define VA_COPY(dest, src) __va_copy(dest, src)
959 #define VA_COPY(dest, src) (dest) = (src)
963 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
971 len = vsnprintf(NULL, 0, fmt, ap2);
973 ret = _talloc(t, len+1);
976 vsnprintf(ret, len+1, fmt, ap2);
977 talloc_set_name_const(ret, ret);
985 Perform string formatting, and return a pointer to newly allocated
986 memory holding the result, inside a memory pool.
988 char *talloc_asprintf(const void *t, const char *fmt, ...)
994 ret = talloc_vasprintf(t, fmt, ap);
1001 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1002 * and return @p s, which may have moved. Good for gradually
1003 * accumulating output into a string buffer.
1006 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1007 PRINTF_ATTRIBUTE(2,0);
1009 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1011 struct talloc_chunk *tc;
1016 return talloc_vasprintf(NULL, fmt, ap);
1019 tc = talloc_chunk_from_ptr(s);
1023 s_len = tc->size - 1;
1024 len = vsnprintf(NULL, 0, fmt, ap2);
1026 s = talloc_realloc(NULL, s, char, s_len + len+1);
1027 if (!s) return NULL;
1031 vsnprintf(s+s_len, len+1, fmt, ap2);
1032 talloc_set_name_const(s, s);
1038 Realloc @p s to append the formatted result of @p fmt and return @p
1039 s, which may have moved. Good for gradually accumulating output
1040 into a string buffer.
1042 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1047 s = talloc_vasprintf_append(s, fmt, ap);
1053 alloc an array, checking for integer overflow in the array size
1055 void *_talloc_array(const void *ctx, size_t el_size, unsigned count,
1058 if (count >= MAX_TALLOC_SIZE/el_size) {
1061 return talloc_named_const(ctx, el_size * count, name);
1065 alloc an zero array, checking for integer overflow in the array size
1067 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count,
1070 if (count >= MAX_TALLOC_SIZE/el_size) {
1073 return _talloc_zero(ctx, el_size * count, name);
1078 realloc an array, checking for integer overflow in the array size
1080 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size,
1081 unsigned count, const char *name)
1083 if (count >= MAX_TALLOC_SIZE/el_size) {
1086 return _talloc_realloc(ctx, ptr, el_size * count, name);
1090 a function version of talloc_realloc(), so it can be passed as a function
1091 pointer to libraries that want a realloc function (a realloc function
1092 encapsulates all the basic capabilities of an allocation library, which is
1095 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1097 return _talloc_realloc(context, ptr, size, NULL);
1101 static void talloc_autofree(void)
1103 talloc_free(cleanup_context);
1104 cleanup_context = NULL;
1108 return a context which will be auto-freed on exit
1109 this is useful for reducing the noise in leak reports
1111 void *talloc_autofree_context(void)
1113 if (cleanup_context == NULL) {
1114 cleanup_context = talloc_named_const(NULL, 0,
1115 "autofree_context");
1116 atexit(talloc_autofree);
1118 return cleanup_context;
1121 size_t talloc_get_size(const void *context)
1123 struct talloc_chunk *tc;
1125 if (context == NULL)
1128 tc = talloc_chunk_from_ptr(context);