Re: allocating memory for array of pointers to char

From: xarax (xarax_at_email.com)
Date: 03/08/04


Date: Mon, 08 Mar 2004 15:58:14 GMT


"Aaron Walker" <ka0ttic@cfl.rr.com> wrote in message
news:pan.2004.03.08.15.31.50.296271@cfl.rr.com...
> On Mon, 08 Mar 2004 12:33:18 +0000, Richard Bos wrote:
>
> > Irrelevant code, OK, but please do leave in all declarations. For
> > checking up on allocation and so on, the types of your objects are
> > important.
>
> First of all, thanks for the response.
>
> >
> >> option->nvalue = nvalue;
> >> option->value = calloc(nvalue, sizeof(char *));
> >
> > How is option declared? If option->value is a pointer (it seems to be a
> > char **), note that calloc() allocates all-bits-zero memory, and all-
> > bits-zero is not guaranteed to be a null pointer. You might as well use
> > malloc() and possibly save some cycles.
>
> option is a pointer to a structure, which is encapsulated in a void
> pointer inside a linked-list element. Once option is filled in, its
> appended to the linked list.
>
> >
> >> for(j = 0; j < nvalue; j++)
> >> {
> >> register int a;
> >
> > It is rarely useful to specify register yourself; your compiler is
> > likely to be better at optimisation at that level than you, these days.
> >
> >> char value[sizeof(buf)];
> >>
> >> for(a = 0; !isspace(buf[i]); a++, i++)
> >> value[a] = buf[i];
> >> value[a] = '\0';
> >>
> >> option->value = ec_strdup(value);

See NOTE #1 below:

> >> FYI, ec_strdup() just calls malloc() and strcpy().
> >
> > How? That's important, you know.
>
> char *
> ec_strdup(const char *str)
> {
> char *cp;
>
> cp = malloc(strlen(str) + 1);
> strcpy(cp, str);
>
> return cp;
> }
>
> >
> >> I tried the above w/o the calloc() first, but it segfaults.
> >

/snip/

> >> Doing it this way works, although I get
> >> "free(): invalid pointer 0x804b838!" when trying to free option->value[0]
> >> (for the same exact "value" each time) at runtime,
> >
> > Well, if you want to free(option->value[0]), you need to point
> > option->value[0] at allocated memory. The way you have it above,
> > option->value probably points at allocated memory, and option->value[0]
> > probably does not.
>
> even though I do: option->value[j] = ec_strdup() ?

NOTE #1: Your posted code didn't specify [j].

> I cannot loop 0 through option->nvalue (number of values in option->value) and
free()?

You probably want to loop up to option->nvalue-1.

>
> >
> >> Is this improper? If so, what would I need to do?

It is proper, as long as it is implemented correctly.

> > The first thing you need to do is sit down, not behind a keyboard but
> > behind a piece of paper, and design your data structures, thoroughly.
>
> I've spent quite a few hours on a notepad, actually. I've just never
> messed with pointers to pointers that much, especially dynamically
> allocated ones.. This is also the first time I've used linked lists, so
> maybe the number of pointers and all the indirection is confusing me.
>
> >
> >> I can't just calloc() since the length of each char pointer is variable,
right?
> >
> > No, the length of a char pointer is sizeof (char *). But possibly each
> > char * points at a different size block of memory.
> >
> > Richard
>
> Ok, I'll try this again ;)
>
> <code>
>
> typedef struct listelem_t {
> void *data;
> struct listelem_t *next;
> } ListElem;
>
> typedef struct {
> ListElem *head;
> ListElem *tail;
>
> int size;
> void (*cleanup)(void *data);
> } List;
>
> typedef struct {
> char *key;
> char **value;

"value" is a pointer to an array of unknown length. Each
element of the array is a (char*).

> int nvalue;

Apparently, this is the number of elements in
the array to which "value" points.

> } ConfigOption;
>
> static List *list;
> static void cleanup_options(void *);
>
> void
> read_config(char *config_file)
> {
> ...
> list = ec_malloc(sizeof(List)); /* ec_malloc() is just an error
> checking wrapper */
>
> create_list(list, &cleanup_options);
> ...
> while(fgets(...)) {
> int i, j;
> int nvalue;
> char inside_word;
> char key[sizeof(buf)];
> ConfigOption *option;
> ...
> option = ec_malloc(sizeof(ConfigOption));
> ...
> option->key = ec_strdup(key);
> ...

Somehow calculated the number of values "nvalue".

> option->nvalue = nvalue;

Assign number of elements of type (char*).

> option->value = ec_calloc(nvalue, sizeof(char *));

Allocate an array of the appropriate size with
all bits set to zero. Subsequent code is intended
to assign all elements, so there is no worry about
portability regarding the NULL pointer value.

>
> for( /* loop through nvalue... */ ) {

Hopefully, looping 0 through nvalue-1.

> char value[sizeof(buf)];
> ...

Somehow copied the isolated char array
from "buf" into a local char array "value".
I didn't see any error checking for zero
length strings. What happens when there
are two adjacent space characters?

> option->value[j] = ec_strdup(value);

Now it appears that you are indexing "value" with "[j]".
This wasn't in your original post.

> }
>
> insert_elem(list, list->tail, (void *)option);
> ...
> }
> ...
> }
>
> /* this gets set to the cleanup member of struct List
> * and gets called for each list element in cleanup_list()
> */
> static void
> cleanup_options(void *data)
> {
> int i;
> ConfigOption *option = (ConfigOption *)data;
>
> free(option->key);
>
> /* I get the free() message on the first interation
> * of this loop for the only multi-value element in
> * linked-list
> */
> for(i = 0; i < option->nvalue; i++)
> free(option->nvalue[i]);

You are deferencing an integer. You probably
want to "free(option->value[i]);".

>
> free(option->nvalue);

You are freeing an integer. You probably
want to "free(option->value);".

> free(option);
> }
> </code>
>
> After typing that last function in (the code is currently on my laptop, so
> I can't cut & paste), I had an idea of what I might be doing wrong (as far
> as the free'ing goes). You were saying about option->value[i] not
> pointing to allocated memory. Is it because I need to dereference it
> above?
>
> Hope this is enough for you to understand what I am trying to do. Once
> again, thanks very much for your help.
>
> Aaron

-- 
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS!
Are ISV upgrade fees too high? Check our custom product development!


Relevant Pages

  • Re: Newbie on the lose.. How to add an unknown length dataset to an array
    ... allocation, it does require enough virtual memory to hold twice the ... consisting of one of these records plus a pointer. ... Having read all the data into the list, I know the size of the array ... and your pointer method makes good sense from since it dosen't ...
    (comp.lang.fortran)
  • Re: allocating memory for array of pointers to char
    ... > checking up on allocation and so on, the types of your objects are ... > bits-zero is not guaranteed to be a null pointer. ... This is also the first time I've used linked lists, ... typedef struct listelem_t { ...
    (comp.lang.c)
  • Re: Ancient history
    ... If a pointer holds origin, ... > segment of memory wholly contained within a single allocation ... > into one allocation into a pointer into another. ... dimensional array to a subroutine with a one dimensional dummy argument. ...
    (sci.crypt)
  • Re: Aaahhrg! Trouble passing an array of structs to a function!
    ... I like your idea of using a pointer to void as a parameter. ... This is understood as I can compare the data from the array passed in to the ... typedef struct pc_g{ ...
    (microsoft.public.vc.language)
  • Re: allocating space for Node**
    ... you should avoid this style of allocation. ... >my image is pointed to by "source" pointer, to allocate space for the table i ... CArray is a bit clumsy for 2D arrays because there's a problem with assignment ... Given you haven't constructed the array elements, ...
    (microsoft.public.vc.mfc)