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 ** NOTE! The following LGPL license applies to the talloc
11 ** library. This does NOT imply that all of Samba is released
14 This library is free software; you can redistribute it and/or
15 modify it under the terms of the GNU Lesser General Public
16 License as published by the Free Software Foundation; either
17 version 2 of the License, or (at your option) any later version.
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
24 You should have received a copy of the GNU Lesser General Public
25 License along with this library; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 inspired by http://swapped.cc/halloc/
40 #ifdef HAVE_SYS_TYPES_H
41 #include <sys/types.h>
60 /* use this to force every realloc to change the pointer, to stress test
61 code that might not cope */
62 #define ALWAYS_REALLOC 0
65 #define MAX_TALLOC_SIZE 0x10000000
66 #define TALLOC_MAGIC 0xe814ec70
67 #define TALLOC_FLAG_FREE 0x01
68 #define TALLOC_FLAG_LOOP 0x02
69 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
71 /* by default we abort when given a bad pointer (such as when talloc_free() is called
72 on a pointer that came from malloc() */
74 #define TALLOC_ABORT(reason) abort()
77 #ifndef discard_const_p
78 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
79 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
81 # define discard_const_p(type, ptr) ((type *)(ptr))
85 /* this null_context is only used if talloc_enable_leak_report() or
86 talloc_enable_leak_report_full() is called, otherwise it remains
89 static const void *null_context;
90 static void *cleanup_context;
93 struct talloc_reference_handle {
94 struct talloc_reference_handle *next, *prev;
98 typedef int (*talloc_destructor_t)(void *);
100 struct talloc_chunk {
101 struct talloc_chunk *next, *prev;
102 struct talloc_chunk *parent, *child;
103 struct talloc_reference_handle *refs;
104 talloc_destructor_t destructor;
110 /* 16 byte alignment seems to keep everyone happy */
111 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
112 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
114 /* panic if we get a bad magic value */
115 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
117 const char *pp = ptr;
118 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
119 if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
120 TALLOC_ABORT("Bad talloc magic value - unknown value");
122 if (tc->flags & TALLOC_FLAG_FREE) {
123 TALLOC_ABORT("Bad talloc magic value - double free");
128 /* hook into the front of the list */
129 #define _TLIST_ADD(list, p) \
133 (p)->next = (p)->prev = NULL; \
135 (list)->prev = (p); \
136 (p)->next = (list); \
142 /* remove an element from a list - element doesn't have to be in list. */
143 #define _TLIST_REMOVE(list, p) \
145 if ((p) == (list)) { \
146 (list) = (p)->next; \
147 if (list) (list)->prev = NULL; \
149 if ((p)->prev) (p)->prev->next = (p)->next; \
150 if ((p)->next) (p)->next->prev = (p)->prev; \
152 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
157 return the parent chunk of a pointer
159 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
161 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
162 while (tc->prev) tc=tc->prev;
166 void *talloc_parent(const void *ptr)
168 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
169 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
173 Allocate a bit of memory as a child of an existing pointer
175 void *_talloc(const void *context, size_t size)
177 struct talloc_chunk *tc;
179 if (context == NULL) {
180 context = null_context;
183 if (size >= MAX_TALLOC_SIZE) {
187 tc = malloc(TC_HDR_SIZE+size);
188 if (tc == NULL) return NULL;
191 tc->flags = TALLOC_MAGIC;
192 tc->destructor = NULL;
198 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
203 parent->child->parent = NULL;
206 _TLIST_ADD(parent->child, tc);
208 tc->next = tc->prev = tc->parent = NULL;
211 return TC_PTR_FROM_CHUNK(tc);
216 setup a destructor to be called on free of a pointer
217 the destructor should return 0 on success, or -1 on failure.
218 if the destructor fails then the free is failed, and the memory can
219 be continued to be used
221 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
223 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
224 tc->destructor = destructor;
228 increase the reference count on a piece of memory.
230 void talloc_increase_ref_count(const void *ptr)
232 talloc_reference(null_context, ptr);
236 helper for talloc_reference()
238 static int talloc_reference_destructor(void *ptr)
240 struct talloc_reference_handle *handle = ptr;
241 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
242 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
243 if (tc1->destructor != (talloc_destructor_t)-1) {
244 tc1->destructor = NULL;
246 _TLIST_REMOVE(tc2->refs, handle);
252 make a secondary reference to a pointer, hanging off the given context.
253 the pointer remains valid until both the original caller and this given
256 the major use for this is when two different structures need to reference the
257 same underlying data, and you want to be able to free the two instances separately,
260 void *talloc_reference(const void *context, const void *ptr)
262 struct talloc_chunk *tc;
263 struct talloc_reference_handle *handle;
264 if (ptr == NULL) return NULL;
266 tc = talloc_chunk_from_ptr(ptr);
267 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
269 if (handle == NULL) return NULL;
271 /* note that we hang the destructor off the handle, not the
272 main context as that allows the caller to still setup their
273 own destructor on the context if they want to */
274 talloc_set_destructor(handle, talloc_reference_destructor);
275 handle->ptr = discard_const_p(void, ptr);
276 _TLIST_ADD(tc->refs, handle);
281 remove a secondary reference to a pointer. This undo's what
282 talloc_reference() has done. The context and pointer arguments
283 must match those given to a talloc_reference()
285 static int talloc_unreference(const void *context, const void *ptr)
287 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
288 struct talloc_reference_handle *h;
290 if (context == NULL) {
291 context = null_context;
294 for (h=tc->refs;h;h=h->next) {
295 struct talloc_chunk *p = talloc_parent_chunk(h);
297 if (context == NULL) break;
298 } else if (TC_PTR_FROM_CHUNK(p) == context) {
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) != talloc_parent_chunk(ptr)) {
343 tc_p = talloc_chunk_from_ptr(ptr);
345 if (tc_p->refs == NULL) {
346 return talloc_free(ptr);
349 new_p = talloc_parent_chunk(tc_p->refs);
351 new_parent = TC_PTR_FROM_CHUNK(new_p);
356 if (talloc_unreference(new_parent, ptr) != 0) {
360 talloc_steal(new_parent, ptr);
366 add a name to an existing pointer - va_list version
368 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
370 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
372 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
373 tc->name = talloc_vasprintf(ptr, fmt, ap);
375 talloc_set_name_const(tc->name, ".name");
380 add a name to an existing pointer
382 void talloc_set_name(const void *ptr, const char *fmt, ...)
386 talloc_set_name_v(ptr, fmt, ap);
391 more efficient way to add a name to a pointer - the name must point to a
394 void talloc_set_name_const(const void *ptr, const char *name)
396 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
401 create a named talloc pointer. Any talloc pointer can be named, and
402 talloc_named() operates just like talloc() except that it allows you
405 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
410 ptr = _talloc(context, size);
411 if (ptr == NULL) return NULL;
414 talloc_set_name_v(ptr, fmt, ap);
421 create a named talloc pointer. Any talloc pointer can be named, and
422 talloc_named() operates just like talloc() except that it allows you
425 void *talloc_named_const(const void *context, size_t size, const char *name)
429 ptr = _talloc(context, size);
434 talloc_set_name_const(ptr, name);
440 return the name of a talloc ptr, or "UNNAMED"
442 const char *talloc_get_name(const void *ptr)
444 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
445 if (tc->name == TALLOC_MAGIC_REFERENCE) {
456 check if a pointer has the given name. If it does, return the pointer,
457 otherwise return NULL
459 void *talloc_check_name(const void *ptr, const char *name)
462 if (ptr == NULL) return NULL;
463 pname = talloc_get_name(ptr);
464 if (pname == name || strcmp(pname, name) == 0) {
465 return discard_const_p(void, ptr);
472 this is for compatibility with older versions of talloc
474 void *talloc_init(const char *fmt, ...)
479 ptr = _talloc(NULL, 0);
480 if (ptr == NULL) return NULL;
483 talloc_set_name_v(ptr, fmt, ap);
490 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
491 should probably not be used in new code. It's in here to keep the talloc
492 code consistent across Samba 3 and 4.
494 void talloc_free_children(void *ptr)
496 struct talloc_chunk *tc;
502 tc = talloc_chunk_from_ptr(ptr);
505 /* we need to work out who will own an abandoned child
506 if it cannot be freed. In priority order, the first
507 choice is owner of any remaining reference to this
508 pointer, the second choice is our parent, and the
509 final choice is the null context. */
510 void *child = TC_PTR_FROM_CHUNK(tc->child);
511 const void *new_parent = null_context;
512 if (tc->child->refs) {
513 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
514 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
516 if (talloc_free(child) == -1) {
517 if (new_parent == null_context) {
518 struct talloc_chunk *p = talloc_parent_chunk(ptr);
519 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
521 talloc_steal(new_parent, child);
527 free a talloc pointer. This also frees all child pointers of this
530 return 0 if the memory is actually freed, otherwise -1. The memory
531 will not be freed if the ref_count is > 1 or the destructor (if
532 any) returns non-zero
534 int talloc_free(void *ptr)
536 struct talloc_chunk *tc;
542 tc = talloc_chunk_from_ptr(ptr);
545 talloc_reference_destructor(tc->refs);
549 if (tc->flags & TALLOC_FLAG_LOOP) {
550 /* we have a free loop - stop looping */
554 if (tc->destructor) {
555 talloc_destructor_t d = tc->destructor;
556 if (d == (talloc_destructor_t)-1) {
559 tc->destructor = (talloc_destructor_t)-1;
564 tc->destructor = NULL;
567 tc->flags |= TALLOC_FLAG_LOOP;
569 talloc_free_children(ptr);
572 _TLIST_REMOVE(tc->parent->child, tc);
573 if (tc->parent->child) {
574 tc->parent->child->parent = tc->parent;
577 if (tc->prev) tc->prev->next = tc->next;
578 if (tc->next) tc->next->prev = tc->prev;
581 tc->flags |= TALLOC_FLAG_FREE;
590 A talloc version of realloc. The context argument is only used if
593 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
595 struct talloc_chunk *tc;
598 /* size zero is equivalent to free() */
604 if (size >= MAX_TALLOC_SIZE) {
608 /* realloc(NULL) is equavalent to malloc() */
610 return talloc_named_const(context, size, name);
613 tc = talloc_chunk_from_ptr(ptr);
615 /* don't allow realloc on referenced pointers */
620 /* by resetting magic we catch users of the old memory */
621 tc->flags |= TALLOC_FLAG_FREE;
624 new_ptr = malloc(size + TC_HDR_SIZE);
626 memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
630 new_ptr = realloc(tc, size + TC_HDR_SIZE);
633 tc->flags &= ~TALLOC_FLAG_FREE;
638 tc->flags &= ~TALLOC_FLAG_FREE;
640 tc->parent->child = new_ptr;
643 tc->child->parent = new_ptr;
654 talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
656 return TC_PTR_FROM_CHUNK(tc);
660 move a lump of memory from one talloc context to another return the
661 ptr on success, or NULL if it could not be transferred.
662 passing NULL as ptr will always return NULL with no side effects.
664 void *talloc_steal(const void *new_ctx, const void *ptr)
666 struct talloc_chunk *tc, *new_tc;
672 if (new_ctx == NULL) {
673 new_ctx = null_context;
676 tc = talloc_chunk_from_ptr(ptr);
678 if (new_ctx == NULL) {
680 _TLIST_REMOVE(tc->parent->child, tc);
681 if (tc->parent->child) {
682 tc->parent->child->parent = tc->parent;
685 if (tc->prev) tc->prev->next = tc->next;
686 if (tc->next) tc->next->prev = tc->prev;
689 tc->parent = tc->next = tc->prev = NULL;
690 return discard_const_p(void, ptr);
693 new_tc = talloc_chunk_from_ptr(new_ctx);
696 return discard_const_p(void, ptr);
700 _TLIST_REMOVE(tc->parent->child, tc);
701 if (tc->parent->child) {
702 tc->parent->child->parent = tc->parent;
705 if (tc->prev) tc->prev->next = tc->next;
706 if (tc->next) tc->next->prev = tc->prev;
710 if (new_tc->child) new_tc->child->parent = NULL;
711 _TLIST_ADD(new_tc->child, tc);
713 return discard_const_p(void, ptr);
717 return the total size of a talloc pool (subtree)
719 off_t talloc_total_size(const void *ptr)
722 struct talloc_chunk *c, *tc;
731 tc = talloc_chunk_from_ptr(ptr);
733 if (tc->flags & TALLOC_FLAG_LOOP) {
737 tc->flags |= TALLOC_FLAG_LOOP;
740 for (c=tc->child;c;c=c->next) {
741 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
744 tc->flags &= ~TALLOC_FLAG_LOOP;
750 return the total number of blocks in a talloc pool (subtree)
752 off_t talloc_total_blocks(const void *ptr)
755 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
757 if (tc->flags & TALLOC_FLAG_LOOP) {
761 tc->flags |= TALLOC_FLAG_LOOP;
764 for (c=tc->child;c;c=c->next) {
765 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
768 tc->flags &= ~TALLOC_FLAG_LOOP;
774 return the number of external references to a pointer
776 static int talloc_reference_count(const void *ptr)
778 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
779 struct talloc_reference_handle *h;
782 for (h=tc->refs;h;h=h->next) {
789 report on memory usage by all children of a pointer, giving a full tree view
791 void talloc_report_depth(const void *ptr, FILE *f, int depth)
793 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
795 if (tc->flags & TALLOC_FLAG_LOOP) {
799 tc->flags |= TALLOC_FLAG_LOOP;
801 for (c=tc->child;c;c=c->next) {
802 if (c->name == TALLOC_MAGIC_REFERENCE) {
803 struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
804 const char *name2 = talloc_get_name(handle->ptr);
805 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
807 const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
808 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
811 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
812 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
813 talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
814 talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
817 tc->flags &= ~TALLOC_FLAG_LOOP;
821 report on memory usage by all children of a pointer, giving a full tree view
823 void talloc_report_full(const void *ptr, FILE *f)
828 if (ptr == NULL) return;
830 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
831 talloc_get_name(ptr),
832 (unsigned long)talloc_total_size(ptr),
833 (unsigned long)talloc_total_blocks(ptr));
835 talloc_report_depth(ptr, f, 1);
840 report on memory usage by all children of a pointer
842 void talloc_report(const void *ptr, FILE *f)
844 struct talloc_chunk *c, *tc;
849 if (ptr == NULL) return;
851 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
852 talloc_get_name(ptr),
853 (unsigned long)talloc_total_size(ptr),
854 (unsigned long)talloc_total_blocks(ptr));
856 tc = talloc_chunk_from_ptr(ptr);
858 for (c=tc->child;c;c=c->next) {
859 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
860 talloc_get_name(TC_PTR_FROM_CHUNK(c)),
861 (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
862 (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
868 report on any memory hanging off the null context
870 static void talloc_report_null(void)
872 if (talloc_total_size(null_context) != 0) {
873 talloc_report(null_context, stderr);
878 report on any memory hanging off the null context
880 static void talloc_report_null_full(void)
882 if (talloc_total_size(null_context) != 0) {
883 talloc_report_full(null_context, stderr);
888 enable tracking of the NULL context
890 void talloc_enable_null_tracking(void)
892 if (null_context == NULL) {
893 null_context = talloc_named_const(NULL, 0, "null_context");
898 enable leak reporting on exit
900 void talloc_enable_leak_report(void)
902 talloc_enable_null_tracking();
903 atexit(talloc_report_null);
907 enable full leak reporting on exit
909 void talloc_enable_leak_report_full(void)
911 talloc_enable_null_tracking();
912 atexit(talloc_report_null_full);
916 talloc and zero memory.
918 void *_talloc_zero(const void *ctx, size_t size, const char *name)
920 void *p = talloc_named_const(ctx, size, name);
923 memset(p, '\0', size);
931 memdup with a talloc.
933 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
935 void *newp = talloc_named_const(t, size, name);
938 memcpy(newp, p, size);
947 char *talloc_strdup(const void *t, const char *p)
953 ret = talloc_memdup(t, p, strlen(p) + 1);
955 talloc_set_name_const(ret, ret);
961 append to a talloced string
963 char *talloc_append_string(const void *t, char *orig, const char *append)
966 size_t olen = strlen(orig);
972 alenz = strlen(append) + 1;
974 ret = talloc_realloc(t, orig, char, olen + alenz);
978 /* append the string with the trailing \0 */
979 memcpy(&ret[olen], append, alenz);
985 strndup with a talloc
987 char *talloc_strndup(const void *t, const char *p, size_t n)
992 for (len=0; len<n && p[len]; len++) ;
994 ret = _talloc(t, len + 1);
995 if (!ret) { return NULL; }
998 talloc_set_name_const(ret, ret);
1004 #define VA_COPY(dest, src) va_copy(dest, src)
1005 #elif defined(HAVE___VA_COPY)
1006 #define VA_COPY(dest, src) __va_copy(dest, src)
1008 #define VA_COPY(dest, src) (dest) = (src)
1012 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1021 /* this call looks strange, but it makes it work on older solaris boxes */
1022 if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
1026 ret = _talloc(t, len+1);
1029 vsnprintf(ret, len+1, fmt, ap2);
1030 talloc_set_name_const(ret, ret);
1038 Perform string formatting, and return a pointer to newly allocated
1039 memory holding the result, inside a memory pool.
1041 char *talloc_asprintf(const void *t, const char *fmt, ...)
1047 ret = talloc_vasprintf(t, fmt, ap);
1054 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1055 * and return @p s, which may have moved. Good for gradually
1056 * accumulating output into a string buffer.
1058 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1060 struct talloc_chunk *tc;
1065 return talloc_vasprintf(NULL, fmt, ap);
1068 tc = talloc_chunk_from_ptr(s);
1072 s_len = tc->size - 1;
1073 if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) {
1074 /* Either the vsnprintf failed or the format resulted in
1075 * no characters being formatted. In the former case, we
1076 * ought to return NULL, in the latter we ought to return
1077 * the original string. Most current callers of this
1078 * function expect it to never return NULL.
1083 s = talloc_realloc(NULL, s, char, s_len + len+1);
1084 if (!s) return NULL;
1088 vsnprintf(s+s_len, len+1, fmt, ap2);
1089 talloc_set_name_const(s, s);
1095 Realloc @p s to append the formatted result of @p fmt and return @p
1096 s, which may have moved. Good for gradually accumulating output
1097 into a string buffer.
1099 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1104 s = talloc_vasprintf_append(s, fmt, ap);
1110 alloc an array, checking for integer overflow in the array size
1112 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1114 if (count >= MAX_TALLOC_SIZE/el_size) {
1117 return talloc_named_const(ctx, el_size * count, name);
1121 alloc an zero array, checking for integer overflow in the array size
1123 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1125 if (count >= MAX_TALLOC_SIZE/el_size) {
1128 return _talloc_zero(ctx, el_size * count, name);
1133 realloc an array, checking for integer overflow in the array size
1135 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1137 if (count >= MAX_TALLOC_SIZE/el_size) {
1140 return _talloc_realloc(ctx, ptr, el_size * count, name);
1144 a function version of talloc_realloc(), so it can be passed as a function pointer
1145 to libraries that want a realloc function (a realloc function encapsulates
1146 all the basic capabilities of an allocation library, which is why this is useful)
1148 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1150 return _talloc_realloc(context, ptr, size, NULL);
1154 static void talloc_autofree(void)
1156 talloc_free(cleanup_context);
1157 cleanup_context = NULL;
1161 return a context which will be auto-freed on exit
1162 this is useful for reducing the noise in leak reports
1164 void *talloc_autofree_context(void)
1166 if (cleanup_context == NULL) {
1167 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1168 atexit(talloc_autofree);
1170 return cleanup_context;
1173 size_t talloc_get_size(const void *context)
1175 struct talloc_chunk *tc;
1177 if (context == NULL)
1180 tc = talloc_chunk_from_ptr(context);
1186 find a parent of this context that has the given name, if any
1188 void *talloc_find_parent_byname(const void *context, const char *name)
1190 struct talloc_chunk *tc;
1192 if (context == NULL) {
1196 tc = talloc_chunk_from_ptr(context);
1198 if (tc->name && strcmp(tc->name, name) == 0) {
1199 return TC_PTR_FROM_CHUNK(tc);
1201 while (tc && tc->prev) tc = tc->prev;
1208 show the parentage of a context
1210 void talloc_show_parents(const void *context, FILE *file)
1212 struct talloc_chunk *tc;
1214 if (context == NULL) {
1215 fprintf(file, "talloc no parents for NULL\n");
1219 tc = talloc_chunk_from_ptr(context);
1220 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1222 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1223 while (tc && tc->prev) tc = tc->prev;