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/
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
56 /* use this to force every realloc to change the pointer, to stress test
57 code that might not cope */
58 #define ALWAYS_REALLOC 0
61 #define MAX_TALLOC_SIZE 0x10000000
62 #define TALLOC_MAGIC 0xe814ec70
63 #define TALLOC_FLAG_FREE 0x01
64 #define TALLOC_FLAG_LOOP 0x02
65 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
67 /* by default we abort when given a bad pointer (such as when talloc_free() is called
68 on a pointer that came from malloc() */
70 #define TALLOC_ABORT(reason) abort()
73 #ifndef discard_const_p
74 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
75 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
77 # define discard_const_p(type, ptr) ((type *)(ptr))
81 /* this null_context is only used if talloc_enable_leak_report() or
82 talloc_enable_leak_report_full() is called, otherwise it remains
85 static const void *null_context;
86 static void *cleanup_context;
89 struct talloc_reference_handle {
90 struct talloc_reference_handle *next, *prev;
94 typedef int (*talloc_destructor_t)(void *);
97 struct talloc_chunk *next, *prev;
98 struct talloc_chunk *parent, *child;
99 struct talloc_reference_handle *refs;
100 talloc_destructor_t destructor;
106 /* 16 byte alignment seems to keep everyone happy */
107 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
108 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
110 /* panic if we get a bad magic value */
111 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
113 const char *pp = ptr;
115 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp);
116 if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
117 TALLOC_ABORT("Bad talloc magic value - unknown value");
119 if (tc->flags & TALLOC_FLAG_FREE) {
120 TALLOC_ABORT("Bad talloc magic value - double free");
125 /* hook into the front of the list */
126 #define _TLIST_ADD(list, p) \
130 (p)->next = (p)->prev = NULL; \
132 (list)->prev = (p); \
133 (p)->next = (list); \
139 /* remove an element from a list - element doesn't have to be in list. */
140 #define _TLIST_REMOVE(list, p) \
142 if ((p) == (list)) { \
143 (list) = (p)->next; \
144 if (list) (list)->prev = NULL; \
146 if ((p)->prev) (p)->prev->next = (p)->next; \
147 if ((p)->next) (p)->next->prev = (p)->prev; \
149 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
154 return the parent chunk of a pointer
156 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
158 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
159 while (tc->prev) tc=tc->prev;
163 void *talloc_parent(const void *ptr)
165 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
166 return TC_PTR_FROM_CHUNK(tc);
170 Allocate a bit of memory as a child of an existing pointer
172 void *_talloc(const void *context, size_t size)
174 struct talloc_chunk *tc;
176 if (context == NULL) {
177 context = null_context;
180 if (size >= MAX_TALLOC_SIZE) {
184 tc = malloc(TC_HDR_SIZE+size);
185 if (tc == NULL) return NULL;
188 tc->flags = TALLOC_MAGIC;
189 tc->destructor = NULL;
195 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
200 parent->child->parent = NULL;
203 _TLIST_ADD(parent->child, tc);
205 tc->next = tc->prev = tc->parent = NULL;
208 return TC_PTR_FROM_CHUNK(tc);
213 setup a destructor to be called on free of a pointer
214 the destructor should return 0 on success, or -1 on failure.
215 if the destructor fails then the free is failed, and the memory can
216 be continued to be used
218 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
220 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
221 tc->destructor = destructor;
225 increase the reference count on a piece of memory.
227 void talloc_increase_ref_count(const void *ptr)
229 talloc_reference(null_context, ptr);
233 helper for talloc_reference()
235 static int talloc_reference_destructor(void *ptr)
237 struct talloc_reference_handle *handle = ptr;
238 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
239 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
240 if (tc1->destructor != (talloc_destructor_t)-1) {
241 tc1->destructor = NULL;
243 _TLIST_REMOVE(tc2->refs, handle);
249 make a secondary reference to a pointer, hanging off the given context.
250 the pointer remains valid until both the original caller and this given
253 the major use for this is when two different structures need to reference the
254 same underlying data, and you want to be able to free the two instances separately,
257 void *talloc_reference(const void *context, const void *ptr)
259 struct talloc_chunk *tc;
260 struct talloc_reference_handle *handle;
261 if (ptr == NULL) return NULL;
263 tc = talloc_chunk_from_ptr(ptr);
264 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
266 if (handle == NULL) return NULL;
268 /* note that we hang the destructor off the handle, not the
269 main context as that allows the caller to still setup their
270 own destructor on the context if they want to */
271 talloc_set_destructor(handle, talloc_reference_destructor);
272 handle->ptr = discard_const_p(void, ptr);
273 _TLIST_ADD(tc->refs, handle);
278 remove a secondary reference to a pointer. This undo's what
279 talloc_reference() has done. The context and pointer arguments
280 must match those given to a talloc_reference()
282 static int talloc_unreference(const void *context, const void *ptr)
284 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
285 struct talloc_reference_handle *h;
287 if (context == NULL) {
288 context = null_context;
291 for (h=tc->refs;h;h=h->next) {
292 struct talloc_chunk *p = talloc_parent_chunk(h);
293 if ((p==NULL && context==NULL) || TC_PTR_FROM_CHUNK(p) == context) break;
299 talloc_set_destructor(h, NULL);
300 _TLIST_REMOVE(tc->refs, h);
306 remove a specific parent context from a pointer. This is a more
307 controlled varient of talloc_free()
309 int talloc_unlink(const void *context, void *ptr)
311 struct talloc_chunk *tc_p, *new_p;
318 if (context == NULL) {
319 context = null_context;
322 if (talloc_unreference(context, ptr) == 0) {
326 if (context == NULL) {
327 if (talloc_parent_chunk(ptr) != NULL) {
331 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
336 tc_p = talloc_chunk_from_ptr(ptr);
338 if (tc_p->refs == NULL) {
339 return talloc_free(ptr);
342 new_p = talloc_parent_chunk(tc_p->refs);
344 new_parent = TC_PTR_FROM_CHUNK(new_p);
349 if (talloc_unreference(new_parent, ptr) != 0) {
353 talloc_steal(new_parent, ptr);
359 add a name to an existing pointer - va_list version
361 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
363 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
365 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
366 tc->name = talloc_vasprintf(ptr, fmt, ap);
368 talloc_set_name_const(tc->name, ".name");
373 add a name to an existing pointer
375 void talloc_set_name(const void *ptr, const char *fmt, ...)
379 talloc_set_name_v(ptr, fmt, ap);
384 more efficient way to add a name to a pointer - the name must point to a
387 void talloc_set_name_const(const void *ptr, const char *name)
389 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
394 create a named talloc pointer. Any talloc pointer can be named, and
395 talloc_named() operates just like talloc() except that it allows you
398 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
403 ptr = _talloc(context, size);
404 if (ptr == NULL) return NULL;
407 talloc_set_name_v(ptr, fmt, ap);
414 create a named talloc pointer. Any talloc pointer can be named, and
415 talloc_named() operates just like talloc() except that it allows you
418 void *talloc_named_const(const void *context, size_t size, const char *name)
422 ptr = _talloc(context, size);
427 talloc_set_name_const(ptr, name);
433 return the name of a talloc ptr, or "UNNAMED"
435 const char *talloc_get_name(const void *ptr)
437 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
438 if (tc->name == TALLOC_MAGIC_REFERENCE) {
449 check if a pointer has the given name. If it does, return the pointer,
450 otherwise return NULL
452 void *talloc_check_name(const void *ptr, const char *name)
455 if (ptr == NULL) return NULL;
456 pname = talloc_get_name(ptr);
457 if (pname == name || strcmp(pname, name) == 0) {
458 return discard_const_p(void, ptr);
465 this is for compatibility with older versions of talloc
467 void *talloc_init(const char *fmt, ...)
472 ptr = _talloc(NULL, 0);
473 if (ptr == NULL) return NULL;
476 talloc_set_name_v(ptr, fmt, ap);
483 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
484 should probably not be used in new code. It's in here to keep the talloc
485 code consistent across Samba 3 and 4.
487 void talloc_free_children(void *ptr)
489 struct talloc_chunk *tc;
495 tc = talloc_chunk_from_ptr(ptr);
498 /* we need to work out who will own an abandoned child
499 if it cannot be freed. In priority order, the first
500 choice is owner of any remaining reference to this
501 pointer, the second choice is our parent, and the
502 final choice is the null context. */
503 void *child = TC_PTR_FROM_CHUNK(tc->child);
504 const void *new_parent = null_context;
505 if (tc->child->refs) {
506 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
507 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
509 if (talloc_free(child) == -1) {
510 if (new_parent == null_context) {
511 struct talloc_chunk *p = talloc_parent_chunk(ptr);
512 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
514 talloc_steal(new_parent, child);
520 free a talloc pointer. This also frees all child pointers of this
523 return 0 if the memory is actually freed, otherwise -1. The memory
524 will not be freed if the ref_count is > 1 or the destructor (if
525 any) returns non-zero
527 int talloc_free(void *ptr)
529 struct talloc_chunk *tc;
535 tc = talloc_chunk_from_ptr(ptr);
538 talloc_reference_destructor(tc->refs);
542 if (tc->flags & TALLOC_FLAG_LOOP) {
543 /* we have a free loop - stop looping */
547 if (tc->destructor) {
548 talloc_destructor_t d = tc->destructor;
549 if (d == (talloc_destructor_t)-1) {
552 tc->destructor = (talloc_destructor_t)-1;
557 tc->destructor = NULL;
560 tc->flags |= TALLOC_FLAG_LOOP;
562 talloc_free_children(ptr);
565 _TLIST_REMOVE(tc->parent->child, tc);
566 if (tc->parent->child) {
567 tc->parent->child->parent = tc->parent;
570 if (tc->prev) tc->prev->next = tc->next;
571 if (tc->next) tc->next->prev = tc->prev;
574 tc->flags |= TALLOC_FLAG_FREE;
583 A talloc version of realloc. The context argument is only used if
586 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
588 struct talloc_chunk *tc;
591 /* size zero is equivalent to free() */
597 if (size >= MAX_TALLOC_SIZE) {
601 /* realloc(NULL) is equavalent to malloc() */
603 return talloc_named_const(context, size, name);
606 tc = talloc_chunk_from_ptr(ptr);
608 /* don't allow realloc on referenced pointers */
613 /* by resetting magic we catch users of the old memory */
614 tc->flags |= TALLOC_FLAG_FREE;
617 new_ptr = malloc(size + TC_HDR_SIZE);
619 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
623 new_ptr = realloc(tc, size + TC_HDR_SIZE);
626 tc->flags &= ~TALLOC_FLAG_FREE;
631 tc->flags &= ~TALLOC_FLAG_FREE;
633 tc->parent->child = new_ptr;
636 tc->child->parent = new_ptr;
647 talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
649 return TC_PTR_FROM_CHUNK(tc);
653 move a lump of memory from one talloc context to another return the
654 ptr on success, or NULL if it could not be transferred.
655 passing NULL as ptr will always return NULL with no side effects.
657 void *talloc_steal(const void *new_ctx, const void *ptr)
659 struct talloc_chunk *tc, *new_tc;
665 if (new_ctx == NULL) {
666 new_ctx = null_context;
669 tc = talloc_chunk_from_ptr(ptr);
671 if (new_ctx == NULL) {
673 _TLIST_REMOVE(tc->parent->child, tc);
674 if (tc->parent->child) {
675 tc->parent->child->parent = tc->parent;
678 if (tc->prev) tc->prev->next = tc->next;
679 if (tc->next) tc->next->prev = tc->prev;
682 tc->parent = tc->next = tc->prev = NULL;
683 return discard_const_p(void, ptr);
686 new_tc = talloc_chunk_from_ptr(new_ctx);
689 return discard_const_p(void, ptr);
693 _TLIST_REMOVE(tc->parent->child, tc);
694 if (tc->parent->child) {
695 tc->parent->child->parent = tc->parent;
698 if (tc->prev) tc->prev->next = tc->next;
699 if (tc->next) tc->next->prev = tc->prev;
703 if (new_tc->child) new_tc->child->parent = NULL;
704 _TLIST_ADD(new_tc->child, tc);
706 return discard_const_p(void, ptr);
710 return the total size of a talloc pool (subtree)
712 off_t talloc_total_size(const void *ptr)
715 struct talloc_chunk *c, *tc;
724 tc = talloc_chunk_from_ptr(ptr);
726 if (tc->flags & TALLOC_FLAG_LOOP) {
730 tc->flags |= TALLOC_FLAG_LOOP;
733 for (c=tc->child;c;c=c->next) {
734 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
737 tc->flags &= ~TALLOC_FLAG_LOOP;
743 return the total number of blocks in a talloc pool (subtree)
745 off_t talloc_total_blocks(const void *ptr)
748 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
750 if (tc->flags & TALLOC_FLAG_LOOP) {
754 tc->flags |= TALLOC_FLAG_LOOP;
757 for (c=tc->child;c;c=c->next) {
758 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
761 tc->flags &= ~TALLOC_FLAG_LOOP;
767 return the number of external references to a pointer
769 static int talloc_reference_count(const void *ptr)
771 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
772 struct talloc_reference_handle *h;
775 for (h=tc->refs;h;h=h->next) {
782 report on memory usage by all children of a pointer, giving a full tree view
784 void talloc_report_depth(const void *ptr, FILE *f, int depth)
786 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
788 if (tc->flags & TALLOC_FLAG_LOOP) {
792 tc->flags |= TALLOC_FLAG_LOOP;
794 for (c=tc->child;c;c=c->next) {
795 if (c->name == TALLOC_MAGIC_REFERENCE) {
796 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
797 const char *name2 = talloc_get_name(handle->ptr);
798 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
800 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
801 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
804 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
805 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
806 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
807 talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
810 tc->flags &= ~TALLOC_FLAG_LOOP;
814 report on memory usage by all children of a pointer, giving a full tree view
816 void talloc_report_full(const void *ptr, FILE *f)
821 if (ptr == NULL) return;
823 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
824 talloc_get_name(ptr),
825 (unsigned long)talloc_total_size(ptr),
826 (unsigned long)talloc_total_blocks(ptr));
828 talloc_report_depth(ptr, f, 1);
833 report on memory usage by all children of a pointer
835 void talloc_report(const void *ptr, FILE *f)
837 struct talloc_chunk *c, *tc;
842 if (ptr == NULL) return;
844 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
845 talloc_get_name(ptr),
846 (unsigned long)talloc_total_size(ptr),
847 (unsigned long)talloc_total_blocks(ptr));
849 tc = talloc_chunk_from_ptr(ptr);
851 for (c=tc->child;c;c=c->next) {
852 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
853 talloc_get_name(TC_PTR_FROM_CHUNK(c)),
854 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
855 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
861 report on any memory hanging off the null context
863 static void talloc_report_null(void)
865 if (talloc_total_size(null_context) != 0) {
866 talloc_report(null_context, stderr);
871 report on any memory hanging off the null context
873 static void talloc_report_null_full(void)
875 if (talloc_total_size(null_context) != 0) {
876 talloc_report_full(null_context, stderr);
881 enable tracking of the NULL context
883 void talloc_enable_null_tracking(void)
885 if (null_context == NULL) {
886 null_context = talloc_named_const(NULL, 0, "null_context");
891 enable leak reporting on exit
893 void talloc_enable_leak_report(void)
895 talloc_enable_null_tracking();
896 atexit(talloc_report_null);
900 enable full leak reporting on exit
902 void talloc_enable_leak_report_full(void)
904 talloc_enable_null_tracking();
905 atexit(talloc_report_null_full);
909 talloc and zero memory.
911 void *_talloc_zero(const void *ctx, size_t size, const char *name)
913 void *p = talloc_named_const(ctx, size, name);
916 memset(p, '\0', size);
924 memdup with a talloc.
926 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
928 void *newp = talloc_named_const(t, size, name);
931 memcpy(newp, p, size);
940 char *talloc_strdup(const void *t, const char *p)
946 ret = talloc_memdup(t, p, strlen(p) + 1);
948 talloc_set_name_const(ret, ret);
954 append to a talloced string
956 char *talloc_append_string(const void *t, char *orig, const char *append)
959 size_t olen = strlen(orig);
960 size_t alenz = strlen(append) + 1;
965 ret = talloc_realloc(t, orig, char, olen + alenz);
969 /* append the string with the trailing \0 */
970 memcpy(&ret[olen], append, alenz);
976 strndup with a talloc
978 char *talloc_strndup(const void *t, const char *p, size_t n)
983 for (len=0; len<n && p[len]; len++) ;
985 ret = _talloc(t, len + 1);
986 if (!ret) { return NULL; }
989 talloc_set_name_const(ret, ret);
995 #define VA_COPY(dest, src) va_copy(dest, src)
996 #elif defined(HAVE___VA_COPY)
997 #define VA_COPY(dest, src) __va_copy(dest, src)
999 #define VA_COPY(dest, src) (dest) = (src)
1003 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1011 len = vsnprintf(NULL, 0, fmt, ap2);
1013 ret = _talloc(t, len+1);
1016 vsnprintf(ret, len+1, fmt, ap2);
1017 talloc_set_name_const(ret, ret);
1025 Perform string formatting, and return a pointer to newly allocated
1026 memory holding the result, inside a memory pool.
1028 char *talloc_asprintf(const void *t, const char *fmt, ...)
1034 ret = talloc_vasprintf(t, fmt, ap);
1041 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1042 * and return @p s, which may have moved. Good for gradually
1043 * accumulating output into a string buffer.
1046 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1048 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1050 struct talloc_chunk *tc;
1055 return talloc_vasprintf(NULL, fmt, ap);
1058 tc = talloc_chunk_from_ptr(s);
1062 s_len = tc->size - 1;
1063 len = vsnprintf(NULL, 0, fmt, ap2);
1065 s = talloc_realloc(NULL, s, char, s_len + len+1);
1066 if (!s) return NULL;
1070 vsnprintf(s+s_len, len+1, fmt, ap2);
1071 talloc_set_name_const(s, s);
1077 Realloc @p s to append the formatted result of @p fmt and return @p
1078 s, which may have moved. Good for gradually accumulating output
1079 into a string buffer.
1081 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1086 s = talloc_vasprintf_append(s, fmt, ap);
1092 alloc an array, checking for integer overflow in the array size
1094 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1096 if (count >= MAX_TALLOC_SIZE/el_size) {
1099 return talloc_named_const(ctx, el_size * count, name);
1103 alloc an zero array, checking for integer overflow in the array size
1105 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1107 if (count >= MAX_TALLOC_SIZE/el_size) {
1110 return _talloc_zero(ctx, el_size * count, name);
1115 realloc an array, checking for integer overflow in the array size
1117 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1119 if (count >= MAX_TALLOC_SIZE/el_size) {
1122 return _talloc_realloc(ctx, ptr, el_size * count, name);
1126 a function version of talloc_realloc(), so it can be passed as a function pointer
1127 to libraries that want a realloc function (a realloc function encapsulates
1128 all the basic capabilities of an allocation library, which is why this is useful)
1130 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1132 return _talloc_realloc(context, ptr, size, NULL);
1136 static void talloc_autofree(void)
1138 talloc_free(cleanup_context);
1139 cleanup_context = NULL;
1143 return a context which will be auto-freed on exit
1144 this is useful for reducing the noise in leak reports
1146 void *talloc_autofree_context(void)
1148 if (cleanup_context == NULL) {
1149 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1150 atexit(talloc_autofree);
1152 return cleanup_context;
1155 size_t talloc_get_size(const void *context)
1157 struct talloc_chunk *tc;
1159 if (context == NULL)
1162 tc = talloc_chunk_from_ptr(context);
1168 find a parent of this context that has the given name, if any
1170 void *talloc_find_parent_byname(const void *context, const char *name)
1172 struct talloc_chunk *tc;
1174 if (context == NULL) {
1178 tc = talloc_chunk_from_ptr(context);
1180 if (tc->name && strcmp(tc->name, name) == 0) {
1181 return TC_PTR_FROM_CHUNK(tc);
1183 while (tc && tc->prev) tc = tc->prev;
1190 show the parentage of a context
1192 void talloc_show_parents(const void *context, FILE *file)
1194 struct talloc_chunk *tc;
1196 if (context == NULL) {
1197 fprintf(file, "talloc no parents for NULL\n");
1201 tc = talloc_chunk_from_ptr(context);
1202 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1204 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1205 while (tc && tc->prev) tc = tc->prev;