[asterisk-dev] reasoning behind char[0]

Kevin P. Fleming kpfleming at digium.com
Wed Sep 30 11:01:05 CDT 2009


Boehm, Matthew wrote:

> I’ve been trying to understand some of the concepts in linkedlist.h and
> loader.c.  My first quandry revolves around the use of “char
> resource[0]” in loader.c, struct ast_module.

That is done because when the 'struct ast_module' is allocated, we
allocate more space than is actually required to hold the structure; in
fact, we allocate enough space for the structure itself, plus the name
of the module being loaded (following by a null byte). After the
allocation is done, the name of the module being loaded is strcpy()-ed
into this extra space, and the result is that 'resource' ends up being a
properly null-terminated string. This is all done in load_dynamic_module().

> In writing my own code examples to understand, I found this along with
> ast_module -> entry -> next to be most troublesome. Nowhere in the code,
> do I find were ->next is set to null, thus preventing AST_LIST_TRAVERSE
> from accessing random memory space. In my code, I always segFaulted on
> the first iteration over the list (containing 1 entry) because the for
> loop tried to access a ->next that didn’t exist because it wasn’t set to
> NULL.

When the 'struct ast_module' is allocated in loader.c
(load_dynamic_module()), that is done using ast_calloc(), which ensures
that all bytes of the allocated memory are set to zero. On all platforms
that Asterisk is expected to work on, NULL is an all-zeroes pointer
value, so this is explicit initialization of the pointer to NULL.

> So I change the behavior of AST_LIST_INSERT_TAIL to, upon !head->first
> to set the .next = NULL. While this worked, this caused a strange
> behavior in the value of resource[0] being truncated or just not set
> correctly.

I do not understand how that could occur; the 'next' pointer and the
'resource' character array do not occupy the same memory space.

> So I was stuck. Not setting .next to NULL allowed resource[] to maintain
> its values but seg’d on any traversing of the list. Setting .next to
> NULL allowed for traversing of the list but put garbled data into the
> values of resource[].
> 
>  
> 
> My only fix was to change resource[0] to char *resource and do an
> ast_calloc on strlen(resource_in) right before the strcpy in
> load_dynamic_module().
> 
>  
> 
> I am now able to have .next = NULL which keeps my traversals sane and
> preserves my values of “resource”.

That should not have been necessary; I would suggest adding a log
statement to load_dynamic_module(), right after the ast_calloc(),
printing out the addresses of resource_being_loaded->resource and
resource_being_loaded->entry->next... something like this:

ast_log(LOG_DEBUG, "resource: %p -- next: %p\n",
resource_being_loaded->resource, &resource_being_loaded->entry->next);

-- 
Kevin P. Fleming
Digium, Inc. | Director of Software Technologies
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA
skype: kpfleming | jabber: kpfleming at digium.com
Check us out at www.digium.com & www.asterisk.org




More information about the asterisk-dev mailing list