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/
32 #if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
33 /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
34 * we trust ourselves... */
49 /* assume a modern system */
53 /* use this to force every realloc to change the pointer, to stress test
54 code that might not cope */
55 #define ALWAYS_REALLOC 0
58 #define MAX_TALLOC_SIZE 0x10000000
59 #define TALLOC_MAGIC 0xe814ec4f
60 #define TALLOC_MAGIC_FREE 0x7faebef3
61 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
63 /* by default we abort when given a bad pointer (such as when talloc_free() is called
64 on a pointer that came from malloc() */
66 #define TALLOC_ABORT(reason) abort()
69 #ifndef discard_const_p
70 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
71 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
73 # define discard_const_p(type, ptr) ((type *)(ptr))
77 /* this null_context is only used if talloc_enable_leak_report() or
78 talloc_enable_leak_report_full() is called, otherwise it remains
81 static const void *null_context
;
82 static void *cleanup_context
;
85 struct talloc_reference_handle
{
86 struct talloc_reference_handle
*next
, *prev
;
90 typedef int (*talloc_destructor_t
)(void *);
93 struct talloc_chunk
*next
, *prev
;
94 struct talloc_chunk
*parent
, *child
;
95 struct talloc_reference_handle
*refs
;
98 talloc_destructor_t destructor
;
102 /* panic if we get a bad magic value */
103 static struct talloc_chunk
*talloc_chunk_from_ptr(const void *ptr
)
105 struct talloc_chunk
*tc
= discard_const_p(struct talloc_chunk
, ptr
)-1;
106 if (tc
->magic
!= TALLOC_MAGIC
) {
107 if (tc
->magic
== TALLOC_MAGIC_FREE
) {
108 TALLOC_ABORT("Bad talloc magic value - double free");
110 TALLOC_ABORT("Bad talloc magic value - unknown value");
117 /* hook into the front of the list */
118 #define _TLIST_ADD(list, p) \
122 (p)->next = (p)->prev = NULL; \
124 (list)->prev = (p); \
125 (p)->next = (list); \
131 /* remove an element from a list - element doesn't have to be in list. */
132 #define _TLIST_REMOVE(list, p) \
134 if ((p) == (list)) { \
135 (list) = (p)->next; \
136 if (list) (list)->prev = NULL; \
138 if ((p)->prev) (p)->prev->next = (p)->next; \
139 if ((p)->next) (p)->next->prev = (p)->prev; \
141 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
146 return the parent chunk of a pointer
148 static struct talloc_chunk
*talloc_parent_chunk(const void *ptr
)
150 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
151 while (tc
->prev
) tc
=tc
->prev
;
155 void *talloc_parent(const void *ptr
)
157 struct talloc_chunk
*tc
= talloc_parent_chunk(ptr
);
158 return (void *)(tc
+1);
162 Allocate a bit of memory as a child of an existing pointer
164 void *_talloc(const void *context
, size_t size
)
166 struct talloc_chunk
*tc
;
168 if (context
== NULL
) {
169 context
= null_context
;
172 if (size
>= MAX_TALLOC_SIZE
) {
176 tc
= malloc(sizeof(*tc
)+size
);
177 if (tc
== NULL
) return NULL
;
180 tc
->magic
= TALLOC_MAGIC
;
181 tc
->destructor
= NULL
;
187 struct talloc_chunk
*parent
= talloc_chunk_from_ptr(context
);
192 parent
->child
->parent
= NULL
;
195 _TLIST_ADD(parent
->child
, tc
);
197 tc
->next
= tc
->prev
= tc
->parent
= NULL
;
200 return (void *)(tc
+1);
205 setup a destructor to be called on free of a pointer
206 the destructor should return 0 on success, or -1 on failure.
207 if the destructor fails then the free is failed, and the memory can
208 be continued to be used
210 void talloc_set_destructor(const void *ptr
, int (*destructor
)(void *))
212 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
213 tc
->destructor
= destructor
;
217 increase the reference count on a piece of memory.
219 void talloc_increase_ref_count(const void *ptr
)
221 talloc_reference(null_context
, ptr
);
225 helper for talloc_reference()
227 static int talloc_reference_destructor(void *ptr
)
229 struct talloc_reference_handle
*handle
= ptr
;
230 struct talloc_chunk
*tc1
= talloc_chunk_from_ptr(ptr
);
231 struct talloc_chunk
*tc2
= talloc_chunk_from_ptr(handle
->ptr
);
232 if (tc1
->destructor
!= (talloc_destructor_t
)-1) {
233 tc1
->destructor
= NULL
;
235 _TLIST_REMOVE(tc2
->refs
, handle
);
241 make a secondary reference to a pointer, hanging off the given context.
242 the pointer remains valid until both the original caller and this given
245 the major use for this is when two different structures need to reference the
246 same underlying data, and you want to be able to free the two instances separately,
249 void *talloc_reference(const void *context
, const void *ptr
)
251 struct talloc_chunk
*tc
;
252 struct talloc_reference_handle
*handle
;
253 if (ptr
== NULL
) return NULL
;
255 tc
= talloc_chunk_from_ptr(ptr
);
256 handle
= talloc_named_const(context
, sizeof(*handle
), TALLOC_MAGIC_REFERENCE
);
258 if (handle
== NULL
) return NULL
;
260 /* note that we hang the destructor off the handle, not the
261 main context as that allows the caller to still setup their
262 own destructor on the context if they want to */
263 talloc_set_destructor(handle
, talloc_reference_destructor
);
264 handle
->ptr
= discard_const_p(void, ptr
);
265 _TLIST_ADD(tc
->refs
, handle
);
270 remove a secondary reference to a pointer. This undo's what
271 talloc_reference() has done. The context and pointer arguments
272 must match those given to a talloc_reference()
274 static int talloc_unreference(const void *context
, const void *ptr
)
276 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
277 struct talloc_reference_handle
*h
;
279 if (context
== NULL
) {
280 context
= null_context
;
283 for (h
=tc
->refs
;h
;h
=h
->next
) {
284 struct talloc_chunk
*p
= talloc_parent_chunk(h
);
285 if ((p
==NULL
&& context
==NULL
) || p
+1 == context
) break;
291 talloc_set_destructor(h
, NULL
);
292 _TLIST_REMOVE(tc
->refs
, h
);
298 remove a specific parent context from a pointer. This is a more
299 controlled varient of talloc_free()
301 int talloc_unlink(const void *context
, void *ptr
)
303 struct talloc_chunk
*tc_p
, *new_p
;
310 if (context
== NULL
) {
311 context
= null_context
;
314 if (talloc_unreference(context
, ptr
) == 0) {
318 if (context
== NULL
) {
319 if (talloc_parent_chunk(ptr
) != NULL
) {
323 if (talloc_chunk_from_ptr(context
) != talloc_parent_chunk(ptr
)) {
328 tc_p
= talloc_chunk_from_ptr(ptr
);
330 if (tc_p
->refs
== NULL
) {
331 return talloc_free(ptr
);
334 new_p
= talloc_parent_chunk(tc_p
->refs
);
336 new_parent
= new_p
+1;
341 if (talloc_unreference(new_parent
, ptr
) != 0) {
345 talloc_steal(new_parent
, ptr
);
351 add a name to an existing pointer - va_list version
353 static void talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
) PRINTF_ATTRIBUTE(2,0);
355 static void talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
)
357 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
358 tc
->name
= talloc_vasprintf(ptr
, fmt
, ap
);
360 talloc_set_name_const(tc
->name
, ".name");
365 add a name to an existing pointer
367 void talloc_set_name(const void *ptr
, const char *fmt
, ...)
371 talloc_set_name_v(ptr
, fmt
, ap
);
376 more efficient way to add a name to a pointer - the name must point to a
379 void talloc_set_name_const(const void *ptr
, const char *name
)
381 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
386 create a named talloc pointer. Any talloc pointer can be named, and
387 talloc_named() operates just like talloc() except that it allows you
390 void *talloc_named(const void *context
, size_t size
, const char *fmt
, ...)
395 ptr
= _talloc(context
, size
);
396 if (ptr
== NULL
) return NULL
;
399 talloc_set_name_v(ptr
, fmt
, ap
);
406 create a named talloc pointer. Any talloc pointer can be named, and
407 talloc_named() operates just like talloc() except that it allows you
410 void *talloc_named_const(const void *context
, size_t size
, const char *name
)
414 ptr
= _talloc(context
, size
);
419 talloc_set_name_const(ptr
, name
);
425 return the name of a talloc ptr, or "UNNAMED"
427 const char *talloc_get_name(const void *ptr
)
429 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
430 if (tc
->name
== TALLOC_MAGIC_REFERENCE
) {
441 check if a pointer has the given name. If it does, return the pointer,
442 otherwise return NULL
444 void *talloc_check_name(const void *ptr
, const char *name
)
447 if (ptr
== NULL
) return NULL
;
448 pname
= talloc_get_name(ptr
);
449 if (pname
== name
|| strcmp(pname
, name
) == 0) {
450 return discard_const_p(void, ptr
);
457 this is for compatibility with older versions of talloc
459 void *talloc_init(const char *fmt
, ...)
464 ptr
= _talloc(NULL
, 0);
465 if (ptr
== NULL
) return NULL
;
468 talloc_set_name_v(ptr
, fmt
, ap
);
475 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
476 should probably not be used in new code. It's in here to keep the talloc
477 code consistent across Samba 3 and 4.
479 void talloc_free_children(void *ptr
)
481 struct talloc_chunk
*tc
;
487 tc
= talloc_chunk_from_ptr(ptr
);
490 /* we need to work out who will own an abandoned child
491 if it cannot be freed. In priority order, the first
492 choice is owner of any remaining reference to this
493 pointer, the second choice is our parent, and the
494 final choice is the null context. */
495 void *child
= tc
->child
+1;
496 const void *new_parent
= null_context
;
497 if (tc
->child
->refs
) {
498 struct talloc_chunk
*p
= talloc_parent_chunk(tc
->child
->refs
);
499 if (p
) new_parent
= p
+1;
501 if (talloc_free(child
) == -1) {
502 if (new_parent
== null_context
) {
503 struct talloc_chunk
*p
= talloc_parent_chunk(ptr
);
504 if (p
) new_parent
= p
+1;
506 talloc_steal(new_parent
, child
);
512 free a talloc pointer. This also frees all child pointers of this
515 return 0 if the memory is actually freed, otherwise -1. The memory
516 will not be freed if the ref_count is > 1 or the destructor (if
517 any) returns non-zero
519 int talloc_free(void *ptr
)
521 struct talloc_chunk
*tc
;
527 tc
= talloc_chunk_from_ptr(ptr
);
530 talloc_reference_destructor(tc
->refs
);
534 if (tc
->destructor
) {
535 talloc_destructor_t d
= tc
->destructor
;
536 if (d
== (talloc_destructor_t
)-1) {
539 tc
->destructor
= (talloc_destructor_t
)-1;
544 tc
->destructor
= NULL
;
547 talloc_free_children(ptr
);
550 _TLIST_REMOVE(tc
->parent
->child
, tc
);
551 if (tc
->parent
->child
) {
552 tc
->parent
->child
->parent
= tc
->parent
;
555 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
556 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
559 tc
->magic
= TALLOC_MAGIC_FREE
;
568 A talloc version of realloc. The context argument is only used if
571 void *_talloc_realloc(const void *context
, void *ptr
, size_t size
, const char *name
)
573 struct talloc_chunk
*tc
;
576 /* size zero is equivalent to free() */
582 if (size
>= MAX_TALLOC_SIZE
) {
586 /* realloc(NULL) is equavalent to malloc() */
588 return talloc_named_const(context
, size
, name
);
591 tc
= talloc_chunk_from_ptr(ptr
);
593 /* don't allow realloc on referenced pointers */
598 /* by resetting magic we catch users of the old memory */
599 tc
->magic
= TALLOC_MAGIC_FREE
;
602 new_ptr
= malloc(size
+ sizeof(*tc
));
604 memcpy(new_ptr
, tc
, tc
->size
+ sizeof(*tc
));
608 new_ptr
= realloc(tc
, size
+ sizeof(*tc
));
611 tc
->magic
= TALLOC_MAGIC
;
616 tc
->magic
= TALLOC_MAGIC
;
618 tc
->parent
->child
= new_ptr
;
621 tc
->child
->parent
= new_ptr
;
632 talloc_set_name_const(tc
+1, name
);
634 return (void *)(tc
+1);
638 move a lump of memory from one talloc context to another return the
639 ptr on success, or NULL if it could not be transferred.
640 passing NULL as ptr will always return NULL with no side effects.
642 void *talloc_steal(const void *new_ctx
, const void *ptr
)
644 struct talloc_chunk
*tc
, *new_tc
;
650 if (new_ctx
== NULL
) {
651 new_ctx
= null_context
;
654 tc
= talloc_chunk_from_ptr(ptr
);
656 if (new_ctx
== NULL
) {
658 _TLIST_REMOVE(tc
->parent
->child
, tc
);
659 if (tc
->parent
->child
) {
660 tc
->parent
->child
->parent
= tc
->parent
;
663 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
664 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
667 tc
->parent
= tc
->next
= tc
->prev
= NULL
;
668 return discard_const_p(void, ptr
);
671 new_tc
= talloc_chunk_from_ptr(new_ctx
);
674 return discard_const_p(void, ptr
);
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
;
688 if (new_tc
->child
) new_tc
->child
->parent
= NULL
;
689 _TLIST_ADD(new_tc
->child
, tc
);
691 return discard_const_p(void, ptr
);
695 return the total size of a talloc pool (subtree)
697 off_t
talloc_total_size(const void *ptr
)
700 struct talloc_chunk
*c
, *tc
;
709 tc
= talloc_chunk_from_ptr(ptr
);
712 for (c
=tc
->child
;c
;c
=c
->next
) {
713 total
+= talloc_total_size(c
+1);
719 return the total number of blocks in a talloc pool (subtree)
721 off_t
talloc_total_blocks(const void *ptr
)
724 struct talloc_chunk
*c
, *tc
= talloc_chunk_from_ptr(ptr
);
727 for (c
=tc
->child
;c
;c
=c
->next
) {
728 total
+= talloc_total_blocks(c
+1);
734 return the number of external references to a pointer
736 static int talloc_reference_count(const void *ptr
)
738 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
739 struct talloc_reference_handle
*h
;
742 for (h
=tc
->refs
;h
;h
=h
->next
) {
749 report on memory usage by all children of a pointer, giving a full tree view
751 void talloc_report_depth(const void *ptr
, FILE *f
, int depth
)
753 struct talloc_chunk
*c
, *tc
= talloc_chunk_from_ptr(ptr
);
755 for (c
=tc
->child
;c
;c
=c
->next
) {
756 if (c
->name
== TALLOC_MAGIC_REFERENCE
) {
757 struct talloc_reference_handle
*handle
= (void *)(c
+1);
758 const char *name2
= talloc_get_name(handle
->ptr
);
759 fprintf(f
, "%*sreference to: %s\n", depth
*4, "", name2
);
761 const char *name
= talloc_get_name(c
+1);
762 fprintf(f
, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
765 (unsigned long)talloc_total_size(c
+1),
766 (unsigned long)talloc_total_blocks(c
+1),
767 talloc_reference_count(c
+1));
768 talloc_report_depth(c
+1, f
, depth
+1);
775 report on memory usage by all children of a pointer, giving a full tree view
777 void talloc_report_full(const void *ptr
, FILE *f
)
782 if (ptr
== NULL
) return;
784 fprintf(f
,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
785 talloc_get_name(ptr
),
786 (unsigned long)talloc_total_size(ptr
),
787 (unsigned long)talloc_total_blocks(ptr
));
789 talloc_report_depth(ptr
, f
, 1);
794 report on memory usage by all children of a pointer
796 void talloc_report(const void *ptr
, FILE *f
)
798 struct talloc_chunk
*c
, *tc
;
803 if (ptr
== NULL
) return;
805 fprintf(f
,"talloc report on '%s' (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 tc
= talloc_chunk_from_ptr(ptr
);
812 for (c
=tc
->child
;c
;c
=c
->next
) {
813 fprintf(f
, "\t%-30s contains %6lu bytes in %3lu blocks\n",
814 talloc_get_name(c
+1),
815 (unsigned long)talloc_total_size(c
+1),
816 (unsigned long)talloc_total_blocks(c
+1));
822 report on any memory hanging off the null context
824 static void talloc_report_null(void)
826 if (talloc_total_size(null_context
) != 0) {
827 talloc_report(null_context
, stderr
);
832 report on any memory hanging off the null context
834 static void talloc_report_null_full(void)
836 if (talloc_total_size(null_context
) != 0) {
837 talloc_report_full(null_context
, stderr
);
842 enable tracking of the NULL context
844 void talloc_enable_null_tracking(void)
846 if (null_context
== NULL
) {
847 null_context
= talloc_named_const(NULL
, 0, "null_context");
852 enable leak reporting on exit
854 void talloc_enable_leak_report(void)
856 talloc_enable_null_tracking();
857 atexit(talloc_report_null
);
861 enable full leak reporting on exit
863 void talloc_enable_leak_report_full(void)
865 talloc_enable_null_tracking();
866 atexit(talloc_report_null_full
);
870 talloc and zero memory.
872 void *_talloc_zero(const void *ctx
, size_t size
, const char *name
)
874 void *p
= talloc_named_const(ctx
, size
, name
);
877 memset(p
, '\0', size
);
885 memdup with a talloc.
887 void *_talloc_memdup(const void *t
, const void *p
, size_t size
, const char *name
)
889 void *newp
= talloc_named_const(t
, size
, name
);
892 memcpy(newp
, p
, size
);
901 char *talloc_strdup(const void *t
, const char *p
)
907 ret
= talloc_memdup(t
, p
, strlen(p
) + 1);
909 talloc_set_name_const(ret
, ret
);
915 strndup with a talloc
917 char *talloc_strndup(const void *t
, const char *p
, size_t n
)
922 for (len
=0; len
<n
&& p
[len
]; len
++) ;
924 ret
= _talloc(t
, len
+ 1);
925 if (!ret
) { return NULL
; }
928 talloc_set_name_const(ret
, ret
);
934 #define VA_COPY(dest, src) va_copy(dest, src)
935 #elif defined(HAVE___VA_COPY)
936 #define VA_COPY(dest, src) __va_copy(dest, src)
938 #define VA_COPY(dest, src) (dest) = (src)
942 char *talloc_vasprintf(const void *t
, const char *fmt
, va_list ap
)
950 len
= vsnprintf(NULL
, 0, fmt
, ap2
);
952 ret
= _talloc(t
, len
+1);
955 vsnprintf(ret
, len
+1, fmt
, ap2
);
956 talloc_set_name_const(ret
, ret
);
964 Perform string formatting, and return a pointer to newly allocated
965 memory holding the result, inside a memory pool.
967 char *talloc_asprintf(const void *t
, const char *fmt
, ...)
973 ret
= talloc_vasprintf(t
, fmt
, ap
);
980 * Realloc @p s to append the formatted result of @p fmt and @p ap,
981 * and return @p s, which may have moved. Good for gradually
982 * accumulating output into a string buffer.
985 static char *talloc_vasprintf_append(char *s
, const char *fmt
, va_list ap
) PRINTF_ATTRIBUTE(2,0);
987 static char *talloc_vasprintf_append(char *s
, const char *fmt
, va_list ap
)
989 struct talloc_chunk
*tc
;
994 return talloc_vasprintf(NULL
, fmt
, ap
);
997 tc
= talloc_chunk_from_ptr(s
);
1001 s_len
= tc
->size
- 1;
1002 len
= vsnprintf(NULL
, 0, fmt
, ap2
);
1004 s
= talloc_realloc(NULL
, s
, char, s_len
+ len
+1);
1005 if (!s
) return NULL
;
1009 vsnprintf(s
+s_len
, len
+1, fmt
, ap2
);
1010 talloc_set_name_const(s
, s
);
1016 Realloc @p s to append the formatted result of @p fmt and return @p
1017 s, which may have moved. Good for gradually accumulating output
1018 into a string buffer.
1020 char *talloc_asprintf_append(char *s
, const char *fmt
, ...)
1025 s
= talloc_vasprintf_append(s
, fmt
, ap
);
1031 alloc an array, checking for integer overflow in the array size
1033 void *_talloc_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
1035 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
1038 return talloc_named_const(ctx
, el_size
* count
, name
);
1042 alloc an zero array, checking for integer overflow in the array size
1044 void *_talloc_zero_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
1046 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
1049 return _talloc_zero(ctx
, el_size
* count
, name
);
1054 realloc an array, checking for integer overflow in the array size
1056 void *_talloc_realloc_array(const void *ctx
, void *ptr
, size_t el_size
, unsigned count
, const char *name
)
1058 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
1061 return _talloc_realloc(ctx
, ptr
, el_size
* count
, name
);
1065 a function version of talloc_realloc(), so it can be passed as a function pointer
1066 to libraries that want a realloc function (a realloc function encapsulates
1067 all the basic capabilities of an allocation library, which is why this is useful)
1069 void *talloc_realloc_fn(const void *context
, void *ptr
, size_t size
)
1071 return _talloc_realloc(context
, ptr
, size
, NULL
);
1075 static void talloc_autofree(void)
1077 talloc_free(cleanup_context
);
1078 cleanup_context
= NULL
;
1082 return a context which will be auto-freed on exit
1083 this is useful for reducing the noise in leak reports
1085 void *talloc_autofree_context(void)
1087 if (cleanup_context
== NULL
) {
1088 cleanup_context
= talloc_named_const(NULL
, 0, "autofree_context");
1089 atexit(talloc_autofree
);
1091 return cleanup_context
;
1094 size_t talloc_get_size(const void *context
)
1096 struct talloc_chunk
*tc
;
1098 if (context
== NULL
)
1101 tc
= talloc_chunk_from_ptr(context
);