diff options
-rw-r--r-- | include/asterisk/stringfields.h | 18 | ||||
-rw-r--r-- | main/utils.c | 69 |
2 files changed, 62 insertions, 25 deletions
diff --git a/include/asterisk/stringfields.h b/include/asterisk/stringfields.h index 9c48bfda2..f3b44fd94 100644 --- a/include/asterisk/stringfields.h +++ b/include/asterisk/stringfields.h @@ -138,6 +138,11 @@ struct ast_string_field_mgr { size_t size; /*!< the total size of the current pool */ size_t used; /*!< the space used in the current pool */ 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 }; /*! @@ -234,15 +239,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); /*! \brief Set a field to a simple string value diff --git a/main/utils.c b/main/utils.c index 4403e5310..8aba624d8 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1368,15 +1368,21 @@ const char __ast_string_field_empty[] = ""; /*!< the empty string */ * 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; - if (!(pool = ast_calloc(1, sizeof(*pool) + size))) +#if defined(__AST_DEBUG_MALLOC) + if (!(pool = __ast_calloc(1, sizeof(*pool) + size, file, lineno, func))) { return -1; - + } +#else + if (!(pool = ast_calloc(1, sizeof(*pool) + size))) { + return -1; + } +#endif + pool->prev = *pool_head; *pool_head = pool; mgr->size = size; @@ -1396,40 +1402,53 @@ 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) *p++ = __ast_string_field_empty; 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; mgr->used = 0; + preserve = *pool_head; + cur = preserve->prev; + } + + if (preserve) { + preserve->prev = NULL; } 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; } @@ -1445,8 +1464,13 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr while (new_size < needed) 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 + mgr->used; @@ -1515,8 +1539,13 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr, while (new_size < needed) 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; +#else + if (add_string_pool(mgr, pool_head, new_size, NULL, 0, NULL)) return; +#endif } target = (*pool_head)->base + mgr->used; |