Inside _talloc_realloc(), keep track of size changes over malloc/realloc/free.
[sfrench/samba-autobuild/.git] / lib / talloc / talloc_guide.txt
index 18663b370d9dc4d8b9aaeae28ef40655cd4d97c4..16afc9b6b8ad0ae671de48535c3653081c1e8794 100644 (file)
@@ -1,11 +1,13 @@
 Using talloc in Samba4
-----------------------
+======================
+
+.. contents::
 
 Andrew Tridgell
-September 2004
+August 2009
 
 The most current version of this document is available at
-   http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt
+   http://samba.org/ftp/unpacked/talloc/talloc_guide.txt
 
 If you are used to the "old" talloc from Samba3 before 3.0.20 then please read
 this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the
@@ -18,13 +20,13 @@ get used to it.
 Perhaps the biggest change from Samba3 is that there is no distinction
 between a "talloc context" and a "talloc pointer". Any pointer
 returned from talloc() is itself a valid talloc context. This means
-you can do this:
+you can do this::
 
   struct foo *X = talloc(mem_ctx, struct foo);
   X->name = talloc_strdup(X, "foo");
 
 and the pointer X->name would be a "child" of the talloc context "X"
-which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx)
+which is itself a child of "mem_ctx". So if you do talloc_free(mem_ctx)
 then it is all destroyed, whereas if you do talloc_free(X) then just X
 and X->name are destroyed, and if you do talloc_free(X->name) then
 just the name element of X is destroyed.
@@ -62,7 +64,7 @@ Multi-threading
 talloc itself does not deal with threads. It is thread-safe (assuming  
 the underlying "malloc" is), as long as each thread uses different  
 memory contexts.
-If two threads uses the same context then they need to synchronize in  
+If two threads use the same context then they need to synchronize in
 order to be safe. In particular:
 - when using talloc_enable_leak_report(), giving directly NULL as a  
 parent context implicitly refers to a hidden "null context" global  
@@ -72,6 +74,19 @@ without proper synchronization ;
 shouldn't be used by several threads simultaneously without  
 synchronization.
 
+talloc and shared objects
+-------------------------
+
+talloc can be used in shared objects. Special care needs to be taken
+to never use talloc_autofree_context() in code that might be loaded
+with dlopen() and unloaded with dlclose(), as talloc_autofree_context()
+internally uses atexit(3). Some platforms like modern Linux handles
+this fine, but for example FreeBSD does not deal well with dlopen()
+and atexit() used simultaneously: dlclose() does not clean up the list
+of atexit-handlers, so when the program exits the code that was
+registered from within talloc_autofree_context() is gone, the program
+crashes at exit.
+
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 (type *)talloc(const void *context, type);
@@ -115,28 +130,41 @@ children. You can call talloc_free() on any pointer returned by
 talloc().
 
 The return value of talloc_free() indicates success or failure, with 0
-returned for success and -1 for failure. The only possible failure
-condition is if the pointer had a destructor attached to it and the
-destructor returned -1. See talloc_set_destructor() for details on
-destructors.
-
-If this pointer has an additional parent when talloc_free() is called
-then the memory is not actually released, but instead the most
-recently established parent is destroyed. See talloc_reference() for
-details on establishing additional parents.
-
-For more control on which parent is removed, see talloc_unlink()
+returned for success and -1 for failure. A possible failure condition
+is if the pointer had a destructor attached to it and the destructor
+returned -1. See talloc_set_destructor() for details on
+destructors. Likewise, if "ptr" is NULL, then the function will make
+no modifications and returns -1.
+
+From version 2.0 and onwards, as a special case, talloc_free() is
+refused on pointers that have more than one parent associated, as talloc
+would have no way of knowing which parent should be removed. This is
+different from older versions in the sense that always the reference to
+the most recently established parent has been destroyed. Hence to free a
+pointer that has more than one parent please use talloc_unlink().
+
+To help you find problems in your code caused by this behaviour, if
+you do try and free a pointer with more than one parent then the
+talloc logging function will be called to give output like this:
+
+  ERROR: talloc_free with references at some_dir/source/foo.c:123
+       reference at some_dir/source/other.c:325
+       reference at some_dir/source/third.c:121
+
+Please see the documentation for talloc_set_log_fn() and
+talloc_set_log_stderr() for more information on talloc logging
+functions.
 
 talloc_free() operates recursively on its children.
 
-
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-int talloc_free_children(void *ptr);
+void talloc_free_children(void *ptr);
 
 The talloc_free_children() walks along the list of all children of a
 talloc context and talloc_free()s only the children, not the context
 itself.
 
+A NULL argument is handled as no-op.
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 void *talloc_reference(const void *context, const void *ptr);
@@ -158,9 +186,9 @@ ways:
     will reduce the number of parents of this pointer by 1, and will
     cause this pointer to be freed if it runs out of parents.
 
-  - you can talloc_free() the pointer itself. That will destroy the
-    most recently established parent to the pointer and leave the
-    pointer as a child of its current parent.
+  - you can talloc_free() the pointer itself if it has at maximum one
+    parent. This behaviour has been changed since the release of version
+    2.0. Further informations in the description of "talloc_free".
 
 For more control on which parent to remove, see talloc_unlink()
 
@@ -176,10 +204,10 @@ Note that if the parent has already been removed using talloc_free()
 then this function will fail and will return -1.  Likewise, if "ptr"
 is NULL, then the function will make no modifications and return -1.
 
-Usually you can just use talloc_free() instead of talloc_unlink(), but
-sometimes it is useful to have the additional control on which parent
-is removed.
-
+You can just use talloc_free() instead of talloc_unlink() if there
+is at maximum one parent. This behaviour has been changed since the
+release of version 2.0. Further informations in the description of
+"talloc_free".
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
@@ -271,7 +299,7 @@ equivalent to:
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 void *talloc_named_const(const void *context, size_t size, const char *name);
 
-This is equivalent to:
+This is equivalent to::
 
    ptr = talloc_size(context, size);
    talloc_set_name_const(ptr, name);
@@ -288,7 +316,7 @@ talloc_set_name() for details.
 void *talloc_init(const char *fmt, ...);
 
 This function creates a zero length named talloc context as a top
-level context. It is equivalent to:
+level context. It is equivalent to::
 
   talloc_named(NULL, 0, fmt, ...);
 
@@ -309,7 +337,7 @@ The talloc_realloc() macro changes the size of a talloc
 pointer. The "count" argument is the number of elements of type "type"
 that you want the resulting pointer to hold. 
 
-talloc_realloc() has the following equivalences:
+talloc_realloc() has the following equivalences::
 
   talloc_realloc(context, NULL, type, 1) ==> talloc(context, type);
   talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N);
@@ -347,6 +375,42 @@ as to your sanity or the safety of your data if you do this.
 
 talloc_steal (new_ctx, NULL) will return NULL with no sideeffects.
 
+Note that if you try and call talloc_steal() on a pointer that has
+more than one parent then the result is ambiguous. Talloc will choose
+to remove the parent that is currently indicated by talloc_parent()
+and replace it with the chosen parent. You will also get a message
+like this via the talloc logging functions:
+
+  WARNING: talloc_steal with references at some_dir/source/foo.c:123
+       reference at some_dir/source/other.c:325
+       reference at some_dir/source/third.c:121
+
+To unambiguously change the parent of a pointer please see the
+function talloc_reparent(). See the talloc_set_log_fn() documentation
+for more information on talloc logging.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+
+The talloc_reparent() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_reparent() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+The difference between talloc_reparent() and talloc_steal() is that
+talloc_reparent() can specify which parent you wish to change. This is
+useful when a pointer has multiple parents via references.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_parent(const void *ptr);
+
+The talloc_parent() function returns the current talloc parent. This
+is usually the pointer under which this memory was originally created,
+but it may have changed due to a talloc_steal() or talloc_reparent()
+
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 size_t talloc_total_size(const void *ptr);
 
@@ -415,7 +479,7 @@ been called.
 void talloc_report_full(const void *ptr, FILE *f);
 
 This provides a more detailed report than talloc_report(). It will
-recursively print the ensire tree of memory referenced by the
+recursively print the entire tree of memory referenced by the
 pointer. References in the tree are shown by giving the name of the
 pointer that is referenced.
 
@@ -490,7 +554,7 @@ This disables tracking of the NULL memory context.
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 (type *)talloc_zero(const void *ctx, type);
 
-The talloc_zero() macro is equivalent to:
+The talloc_zero() macro is equivalent to::
 
   ptr = talloc(ctx, type);
   if (ptr) memset(ptr, 0, sizeof(type));
@@ -505,7 +569,7 @@ The talloc_zero_size() function is useful when you don't have a known type
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 void *talloc_memdup(const void *ctx, const void *p, size_t size);
 
-The talloc_memdup() function is equivalent to:
+The talloc_memdup() function is equivalent to::
 
   ptr = talloc_size(ctx, size);
   if (ptr) memcpy(ptr, p, size);
@@ -514,13 +578,14 @@ The talloc_memdup() function is equivalent to:
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 char *talloc_strdup(const void *ctx, const char *p);
 
-The talloc_strdup() function is equivalent to:
+The talloc_strdup() function is equivalent to::
 
   ptr = talloc_size(ctx, strlen(p)+1);
   if (ptr) memcpy(ptr, p, strlen(p)+1);
 
 This functions sets the name of the new pointer to the passed
-string. This is equivalent to:
+string. This is equivalent to::
+
    talloc_set_name_const(ptr, ptr)
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
@@ -540,7 +605,8 @@ The talloc_append_string() function appends the given formatted
 string to the given string.
 
 This function sets the name of the new pointer to the new
-string. This is equivalent to:
+string. This is equivalent to::
+
    talloc_set_name_const(ptr, ptr)
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
@@ -550,7 +616,8 @@ The talloc_vasprintf() function is the talloc equivalent of the C
 library function vasprintf()
 
 This functions sets the name of the new pointer to the new
-string. This is equivalent to:
+string. This is equivalent to::
+
    talloc_set_name_const(ptr, ptr)
 
 
@@ -561,7 +628,8 @@ The talloc_asprintf() function is the talloc equivalent of the C
 library function asprintf()
 
 This functions sets the name of the new pointer to the new
-string. This is equivalent to:
+string. This is equivalent to::
+
    talloc_set_name_const(ptr, ptr)
 
 
@@ -570,11 +638,12 @@ char *talloc_asprintf_append(char *s, const char *fmt, ...);
 
 The talloc_asprintf_append() function appends the given formatted
 string to the given string.
-Use this varient when the string in the current talloc buffer may
+Use this variant when the string in the current talloc buffer may
 have been truncated in length.
 
 This functions sets the name of the new pointer to the new
-string. This is equivalent to:
+string. This is equivalent to::
+
    talloc_set_name_const(ptr, ptr)
 
 
@@ -583,18 +652,19 @@ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...);
 
 The talloc_asprintf_append() function appends the given formatted 
 string to the end of the currently allocated talloc buffer.
-Use this varient when the string in the current talloc buffer has
+Use this variant when the string in the current talloc buffer has
 not been changed.
 
 This functions sets the name of the new pointer to the new
-string. This is equivalent to:
+string. This is equivalent to::
+
    talloc_set_name_const(ptr, ptr)
 
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-((type *)talloc_array(const void *ctx, type, uint_t count);
+((type *)talloc_array(const void *ctx, type, unsigned int count);
 
-The talloc_array() macro is equivalent to:
+The talloc_array() macro is equivalent to::
 
   (type *)talloc_size(ctx, sizeof(type) * count);
 
@@ -603,14 +673,14 @@ returning NULL if the multiply overflows.
 
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-void *talloc_array_size(const void *ctx, size_t size, uint_t count);
+void *talloc_array_size(const void *ctx, size_t size, unsigned int count);
 
 The talloc_array_size() function is useful when the type is not
 known. It operates in the same way as talloc_array(), but takes a size
 instead of a type.
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);
+(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, unsigned int count);
 
 The talloc_ptrtype() macro should be used when you have a pointer to an array
 and want to allocate memory of an array to point at with this pointer. When compiling
@@ -648,7 +718,7 @@ then the pointer is returned. It it doesn't then NULL is returned.
 
 This macro allows you to do type checking on talloc pointers. It is
 particularly useful for void* private pointers. It is equivalent to
-this:
+this::
 
    (type *)talloc_check_name(ptr, #type)
 
@@ -656,17 +726,18 @@ this:
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 talloc_set_type(const void *ptr, type);
 
-This macro allows you to force the name of a pointer to be a
+This macro allows you to force the name of a pointer to be of a
 particular type. This can be used in conjunction with
 talloc_get_type() to do type checking on void* pointers.
 
-It is equivalent to this:
+It is equivalent to this::
+
    talloc_set_name_const(ptr, #type)
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 talloc_get_size(const void *ctx);
 
-This function lets you know the amount of memory alloced so far by
+This function lets you know the amount of memory allocated so far by
 this context. It does NOT account for subcontext memory.
 This can be used to calculate the size of an array.
 
@@ -683,3 +754,14 @@ know the structure you want is a parent of another context.
 
 Like talloc_find_parent_byname() but takes a type, making it typesafe.
 
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_fn(void (*log_fn)(const char *message));
+
+This function sets a logging function that talloc will use for
+warnings and errors. By default talloc will not print any warnings or
+errors.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_stderr(void)
+
+This sets the talloc log function to write log messages to stderr.