summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/stringfields.h20
-rw-r--r--main/utils.c59
2 files changed, 55 insertions, 24 deletions
diff --git a/include/asterisk/stringfields.h b/include/asterisk/stringfields.h
index c48e9382a..3d59ea12c 100644
--- a/include/asterisk/stringfields.h
+++ b/include/asterisk/stringfields.h
@@ -137,7 +137,12 @@ struct ast_string_field_pool {
\brief Structure used to manage the storage for a set of string fields.
*/
struct ast_string_field_mgr {
- ast_string_field last_alloc; /*!< the last field allocated */
+ ast_string_field last_alloc; /*!< the last field allocated */
+#if defined(__AST_DEBUG_MALLOC)
+ const char *owner_file; /*!< filename of owner */
+ const char *owner_func; /*!< function name of owner */
+ int owner_line; /*!< line number of owner */
+#endif
};
/*!
@@ -235,15 +240,18 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
\return 0 on success, non-zero on failure
*/
#define ast_string_field_init(x, size) \
- __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size)
+ __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*! \brief free all memory - to be called before destroying the object */
#define ast_string_field_free_memory(x) \
- __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1)
+ __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, NULL, 0, NULL)
-/*! \internal \brief internal version of ast_string_field_init */
-int __ast_string_field_init(struct ast_string_field_mgr *mgr,
- struct ast_string_field_pool **pool_head, int needed);
+/*!
+ * \internal
+ * \brief internal version of ast_string_field_init
+ */
+int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
+ int needed, const char *file, int lineno, const char *func);
/*!
\internal
diff --git a/main/utils.c b/main/utils.c
index 57ea0566d..6709e02d1 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -1500,16 +1500,21 @@ static size_t optimal_alloc_size(size_t size)
* We can only allocate from the topmost pool, so the
* fields in *mgr reflect the size of that only.
*/
-static int add_string_pool(struct ast_string_field_mgr *mgr,
- struct ast_string_field_pool **pool_head,
- size_t size)
+static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
+ size_t size, const char *file, int lineno, const char *func)
{
struct ast_string_field_pool *pool;
size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
+#if defined(__AST_DEBUG_MALLOC)
+ if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
+ return -1;
+ }
+#else
if (!(pool = ast_calloc(1, alloc_size))) {
return -1;
}
+#endif
pool->prev = *pool_head;
pool->size = alloc_size - sizeof(*pool);
@@ -1529,12 +1534,12 @@ static int add_string_pool(struct ast_string_field_mgr *mgr,
* size < 0 means release all pools.
* This must be done before destroying the object.
*/
-int __ast_string_field_init(struct ast_string_field_mgr *mgr,
- struct ast_string_field_pool **pool_head,
- int size)
+int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
+ int needed, const char *file, int lineno, const char *func)
{
const char **p = (const char **) pool_head + 1;
- struct ast_string_field_pool *cur = *pool_head;
+ struct ast_string_field_pool *cur = NULL;
+ struct ast_string_field_pool *preserve = NULL;
/* clear fields - this is always necessary */
while ((struct ast_string_field_mgr *) p != mgr) {
@@ -1542,30 +1547,43 @@ int __ast_string_field_init(struct ast_string_field_mgr *mgr,
}
mgr->last_alloc = NULL;
- if (size > 0) { /* allocate the initial pool */
+#if defined(__AST_DEBUG_MALLOC)
+ mgr->owner_file = file;
+ mgr->owner_func = func;
+ mgr->owner_line = lineno;
+#endif
+ if (needed > 0) { /* allocate the initial pool */
*pool_head = NULL;
- return add_string_pool(mgr, pool_head, size);
+ return add_string_pool(mgr, pool_head, needed, file, lineno, func);
}
- if (size < 0) { /* reset all pools */
- *pool_head = NULL;
- } else { /* preserve the first pool */
- if (cur == NULL) {
+ if (needed < 0) { /* reset all pools */
+ /* nothing to do */
+ } else { /* preserve the last pool */
+ if (*pool_head == NULL) {
ast_log(LOG_WARNING, "trying to reset empty pool\n");
return -1;
}
- cur = cur->prev;
- (*pool_head)->prev = NULL;
- (*pool_head)->used = (*pool_head)->active = 0;
+ preserve = *pool_head;
+ cur = preserve->prev;
+ }
+
+ if (preserve) {
+ preserve->prev = NULL;
+ preserve->used = preserve->active = 0;
}
while (cur) {
struct ast_string_field_pool *prev = cur->prev;
- ast_free(cur);
+ if (cur != preserve) {
+ ast_free(cur);
+ }
cur = prev;
}
+ *pool_head = preserve;
+
return 0;
}
@@ -1583,8 +1601,13 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr
new_size *= 2;
}
- if (add_string_pool(mgr, pool_head, new_size))
+#if defined(__AST_DEBUG_MALLOC)
+ if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
return NULL;
+#else
+ if (add_string_pool(mgr, pool_head, new_size, NULL, 0, NULL))
+ return NULL;
+#endif
}
result = (*pool_head)->base + (*pool_head)->used;