summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-09-27 04:20:18 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:59:20 -0500
commit351ca44e8b3ea8336abba8215dfc1ccb42458384 (patch)
tree2a844c622eef52c401a88c53afa05c38e3543436 /source4/lib
parent0be5523afbd9fcc2c08afab708fa6df19035f16e (diff)
downloadsamba-351ca44e8b3ea8336abba8215dfc1ccb42458384.tar.gz
samba-351ca44e8b3ea8336abba8215dfc1ccb42458384.tar.bz2
samba-351ca44e8b3ea8336abba8215dfc1ccb42458384.zip
r2674: I have realised that talloc() should have its context marked const, as
a const pointer really means that "the data pointed to by this pointer won't change", and that is certainly true of talloc(). The fact that some behind-the-scenes meta-data can change doesn't matter from the point of view of const. this fixes a number of const warnings caused by const data structures being passed as talloc contexts. That will no longer generate a warning. also changed the talloc leak reporting option from --leak-check to --leak-report, as all it does is generate a report on exit. A new --leak-report-full option has been added that shows the complete tree of memory allocations, which is is quite useful in tracking things down. NOTE: I find it quite useful to insert talloc_report_full(ptr, stderr) calls at strategic points in the code while debugging memory allocation problems, particularly before freeing a major context (such as the connection context). This allows you to see if that context has been accumulating too much data, such as per-request data, which should have been freed when the request finished. (This used to be commit c60ff99c3129c26a9204bac1c6e5fb386114a923)
Diffstat (limited to 'source4/lib')
-rw-r--r--source4/lib/cmdline/popt_common.c13
-rw-r--r--source4/lib/data_blob.c11
-rw-r--r--source4/lib/talloc.c118
3 files changed, 96 insertions, 46 deletions
diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c
index f98c460642..725a5060c0 100644
--- a/source4/lib/cmdline/popt_common.c
+++ b/source4/lib/cmdline/popt_common.c
@@ -34,7 +34,7 @@
*/
-enum {OPT_OPTION=1,OPT_LEAK_CHECK=2};
+enum {OPT_OPTION=1,OPT_LEAK_REPORT,OPT_LEAK_REPORT_FULL};
static struct cmdline_auth_info cmdline_auth_info;
@@ -117,8 +117,12 @@ static void popt_common_callback(poptContext con,
}
break;
- case OPT_LEAK_CHECK:
- talloc_enable_leak_check();
+ case OPT_LEAK_REPORT:
+ talloc_enable_leak_report();
+ break;
+
+ case OPT_LEAK_REPORT_FULL:
+ talloc_enable_leak_report_full();
break;
}
}
@@ -140,7 +144,8 @@ struct poptOption popt_common_samba[] = {
{ "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" },
{ "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" },
{ "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" },
- { "leak-check", 0, POPT_ARG_NONE, NULL, OPT_LEAK_CHECK, "enable talloc leak checking", NULL },
+ { "leak-report", 0, POPT_ARG_NONE, NULL, OPT_LEAK_REPORT, "enable talloc leak reporting on exit", NULL },
+ { "leak-report-full",0, POPT_ARG_NONE, NULL, OPT_LEAK_REPORT_FULL, "enable full talloc leak reporting on exit", NULL },
POPT_TABLEEND
};
diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c
index b09148b63e..7803179d39 100644
--- a/source4/lib/data_blob.c
+++ b/source4/lib/data_blob.c
@@ -51,17 +51,12 @@ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
/*******************************************************************
construct a data blob, using supplied TALLOC_CTX
*******************************************************************/
-DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
+DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
{
- DATA_BLOB ret = data_blob(p, length);
+ DATA_BLOB ret = data_blob_named(p, length, name);
if (ret.data) {
- ret.data = talloc_steal(mem_ctx, ret.data);
- } else {
- /* this ensures the blob has the context attached, so a zero length call
- to data_blob_talloc followed by a realloc doesn't cause the memory to come
- from the NULL context */
- ret.data = talloc(mem_ctx, 0);
+ talloc_steal(mem_ctx, ret.data);
}
return ret;
}
diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c
index 7266ff8a45..ce8f1c5272 100644
--- a/source4/lib/talloc.c
+++ b/source4/lib/talloc.c
@@ -30,7 +30,7 @@
#define TALLOC_MAGIC 0xe814ec4f
#define TALLOC_MAGIC_FREE 0x7faebef3
-static void *null_context;
+static const void *null_context;
struct talloc_chunk {
struct talloc_chunk *next, *prev;
@@ -43,9 +43,9 @@ struct talloc_chunk {
};
/* panic if we get a bad magic value */
-static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr)
+static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
{
- struct talloc_chunk *tc = ((struct talloc_chunk *)ptr)-1;
+ struct talloc_chunk *tc = ((struct talloc_chunk *)discard_const(ptr))-1;
if (tc->magic != TALLOC_MAGIC) {
if (tc->magic == TALLOC_MAGIC_FREE) {
smb_panic("Bad talloc magic value - double free\n");
@@ -59,7 +59,7 @@ static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr)
/*
Allocate a bit of memory as a child of an existing pointer
*/
-void *_talloc(void *context, size_t size)
+void *_talloc(const void *context, size_t size)
{
struct talloc_chunk *tc;
@@ -107,7 +107,7 @@ void *_talloc(void *context, size_t size)
if the destructor fails then the free is failed, and the memory can
be continued to be used
*/
-void talloc_set_destructor(void *ptr, int (*destructor)(void *))
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->destructor = destructor;
@@ -118,7 +118,7 @@ void talloc_set_destructor(void *ptr, int (*destructor)(void *))
reference count call talloc_free(), which will free the memory if
the reference count reaches zero
*/
-void talloc_increase_ref_count(void *ptr)
+void talloc_increase_ref_count(const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->ref_count++;
@@ -128,9 +128,9 @@ void talloc_increase_ref_count(void *ptr)
/*
add a name to an existing pointer - va_list version
*/
-static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap)
+static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->name = talloc_vasprintf(ptr, fmt, ap);
@@ -139,7 +139,7 @@ static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap)
/*
add a name to an existing pointer
*/
-void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
+void talloc_set_name(const void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
{
va_list ap;
va_start(ap, fmt);
@@ -151,7 +151,7 @@ void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
more efficient way to add a name to a pointer - the name must point to a
true string constant
*/
-void talloc_set_name_const(void *ptr, const char *name)
+void talloc_set_name_const(const void *ptr, const char *name)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->name = name;
@@ -162,7 +162,7 @@ void talloc_set_name_const(void *ptr, const char *name)
talloc_named() operates just like talloc() except that it allows you
to name the pointer.
*/
-void *talloc_named(void *context, size_t size,
+void *talloc_named(const void *context, size_t size,
const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4)
{
va_list ap;
@@ -185,7 +185,7 @@ void *talloc_named(void *context, size_t size,
talloc_named() operates just like talloc() except that it allows you
to name the pointer.
*/
-void *talloc_named_const(void *context, size_t size, const char *name)
+void *talloc_named_const(const void *context, size_t size, const char *name)
{
void *ptr;
@@ -202,7 +202,7 @@ void *talloc_named_const(void *context, size_t size, const char *name)
/*
return the name of a talloc ptr, or "UNNAMED"
*/
-const char *talloc_get_name(void *ptr)
+const char *talloc_get_name(const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
if (tc->name) {
@@ -290,7 +290,7 @@ int talloc_free(void *ptr)
A talloc version of realloc. The context argument is only used if
ptr is NULL
*/
-void *_talloc_realloc(void *context, void *ptr, size_t size, const char *name)
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
{
struct talloc_chunk *tc;
void *new_ptr;
@@ -340,7 +340,7 @@ void *_talloc_realloc(void *context, void *ptr, size_t size, const char *name)
move a lump of memory from one talloc context to another return the
ptr on success, or NUL if it could not be transferred
*/
-void *talloc_steal(void *new_ctx, void *ptr)
+void *talloc_steal(const void *new_ctx, const void *ptr)
{
struct talloc_chunk *tc, *new_tc;
@@ -352,7 +352,7 @@ void *talloc_steal(void *new_ctx, void *ptr)
new_tc = talloc_chunk_from_ptr(new_ctx);
if (tc == new_tc) {
- return ptr;
+ discard_const(ptr);
}
if (tc->parent) {
@@ -369,13 +369,13 @@ void *talloc_steal(void *new_ctx, void *ptr)
if (new_tc->child) new_tc->child->parent = NULL;
DLIST_ADD(new_tc->child, tc);
- return ptr;
+ return discard_const(ptr);
}
/*
return the total size of a talloc pool (subtree)
*/
-static off_t talloc_total_size(void *ptr)
+static off_t talloc_total_size(const void *ptr)
{
off_t total = 0;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
@@ -390,7 +390,7 @@ static off_t talloc_total_size(void *ptr)
/*
return the total number of blocks in a talloc pool (subtree)
*/
-static off_t talloc_total_blocks(void *ptr)
+static off_t talloc_total_blocks(const void *ptr)
{
off_t total = 0;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
@@ -403,9 +403,40 @@ static off_t talloc_total_blocks(void *ptr)
}
/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+static void talloc_report_depth(const void *ptr, FILE *f, int depth)
+{
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ for (c=tc->child;c;c=c->next) {
+ fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks\n",
+ depth*2, "",
+ talloc_get_name(c+1),
+ (unsigned long)talloc_total_size(c+1),
+ (unsigned long)talloc_total_blocks(c+1));
+ talloc_report_depth(c+1, f, depth+1);
+ }
+
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_full(const void *ptr, FILE *f)
+{
+ fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
+ talloc_get_name(ptr),
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+
+ talloc_report_depth(ptr, f, 1);
+}
+
+/*
report on memory usage by all children of a pointer
*/
-void talloc_report(void *ptr, FILE *f)
+void talloc_report(const void *ptr, FILE *f)
{
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
@@ -426,7 +457,7 @@ void talloc_report(void *ptr, FILE *f)
/*
report on any memory hanging off the null context
*/
-static void talloc_report_all(void)
+static void talloc_report_null(void)
{
if (talloc_total_size(null_context) == 0) {
return;
@@ -435,20 +466,40 @@ static void talloc_report_all(void)
}
/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null_full(void)
+{
+ if (talloc_total_size(null_context) == 0) {
+ return;
+ }
+ talloc_report_full(null_context, stderr);
+}
+
+/*
enable leak reporting on exit
*/
-void talloc_enable_leak_check(void)
+void talloc_enable_leak_report(void)
+{
+ null_context = talloc_named_const(NULL, 0, "null_context");
+ atexit(talloc_report_null);
+}
+
+/*
+ enable full leak reporting on exit
+*/
+void talloc_enable_leak_report_full(void)
{
null_context = talloc_named_const(NULL, 0, "null_context");
- atexit(talloc_report_all);
+ atexit(talloc_report_null_full);
}
/*
talloc and zero memory.
*/
-void *talloc_zero(void *t, size_t size)
+void *talloc_zero(const void *ctx, size_t size)
{
- void *p = talloc(t, size);
+ void *p = talloc(ctx, size);
if (p) {
memset(p, '\0', size);
@@ -461,13 +512,12 @@ void *talloc_zero(void *t, size_t size)
/*
memdup with a talloc.
*/
-void *_talloc_memdup(void *t, const void *p, size_t size, const char *name)
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
{
- void *newp = _talloc(t,size);
+ void *newp = talloc_named_const(t, size, name);
if (newp) {
memcpy(newp, p, size);
- talloc_set_name_const(newp, name);
}
return newp;
@@ -476,7 +526,7 @@ void *_talloc_memdup(void *t, const void *p, size_t size, const char *name)
/*
strdup with a talloc
*/
-char *talloc_strdup(void *t, const char *p)
+char *talloc_strdup(const void *t, const char *p)
{
char *ret;
if (!p) {
@@ -492,7 +542,7 @@ char *talloc_strdup(void *t, const char *p)
/*
strndup with a talloc
*/
-char *talloc_strndup(void *t, const char *p, size_t n)
+char *talloc_strndup(const void *t, const char *p, size_t n)
{
size_t len = strnlen(p, n);
char *ret;
@@ -504,7 +554,7 @@ char *talloc_strndup(void *t, const char *p, size_t n)
return ret;
}
-char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0)
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0)
{
int len;
char *ret;
@@ -529,7 +579,7 @@ char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2
Perform string formatting, and return a pointer to newly allocated
memory holding the result, inside a memory pool.
*/
-char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
+char *talloc_asprintf(const void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
{
va_list ap;
char *ret;
@@ -595,7 +645,7 @@ char *talloc_asprintf_append(char *s,
/*
alloc an array, checking for integer overflow in the array size
*/
-void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name)
+void *talloc_array(const void *ctx, size_t el_size, uint_t count, const char *name)
{
if (count == 0 ||
count >= MAX_TALLOC_SIZE/el_size) {
@@ -608,7 +658,7 @@ void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name)
/*
realloc an array, checking for integer overflow in the array size
*/
-void *talloc_realloc_array(void *ctx, void *ptr, size_t el_size, uint_t count, const char *name)
+void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, uint_t count, const char *name)
{
if (count == 0 ||
count >= MAX_TALLOC_SIZE/el_size) {