Re: Explications for malloc ang some questions about pointers

From: Old Wolf (oldwolf_at_inspire.net.nz)
Date: 08/12/04


Date: 11 Aug 2004 19:12:19 -0700

rano@personnalitest.com (Rano) wrote:

> I've got some troubles with a stupid program...
> In fact, I just start with the C language and sometime
> I don't understand how I really have to use malloc.

A pointer is a thing that contains the address of some
block of memory somewhere.

"malloc" allocates a number of bytes and returns a pointer to
the first of the bytes it allocated.

If you want to create a new object of type T, then:
  T *ptr = malloc( sizeof(T) );
because the number of bytes you need to store a T object is
sizeof(T) , not sizeof(T*). Now 'ptr' points to (ie. is the
address of) the object you created.

Also, every time you call "malloc" you should check that the
result is not NULL (ie. indicating that you ran out of memory),
and do something graceful (eg. print "out of memory" and exit()).

You should also have one "free" corresponding to each "malloc",
to release the memory you allocated.

> struct AAtmp
> {
> int name_length;

> char * name;
> int n;
> struct BBtmp **bb;
> };
> typedef struct AAtmp AA;

It's safe to use the same name for the 'struct tag' as for the typedef,
ie. use AA instead of AAtmp.

> AA *createAA(char *name, unsigned int name_length)

It is easier to use C strings instead of length-counted strings.
C strings use the character 0 to indicate their end. So:

  AA *createAA(char const *name)

(the 'const' indicates that what 'name' points to won't be modified.
It helps to avoid you accidentally modifying it).

> {
> AA *a_tmp = malloc(sizeof(AA));
> memset(a_tmp, 0, sizeof(AA));

You have created an object the right size to be an "AA".
"a_tmp" points to it.

>
> // The name
> a_tmp->name_length = (name_length+1);
> a_tmp->name = malloc(name_length+1);
> memcpy(a_tmp->name, name, name_length+1);

I would suggest that "name_length" is not a good name for a
variable if it is actually one more than "name_length".
In fact, using C strings:

  a_tmp->name = malloc( strlen(name) + 1 );
  strcpy(a_tmp->name, name);

> // The BBs'array
> a_tmp->n = 0;
> a_tmp->bb = malloc(sizeof(BB **));
> /************************************************
> Q2) Do i have to malloc (sizeof(BB **) or sizeof(BB *)) ?
> Both have a size of 4, but what is the most clean ?
> If it's like the Q1), I suppose it's sizeof(BB *) no ?
> ************************************************/

I am guessing (see my further comments later..) that this is
meant to be a list of pointers-to-BB, where the things that
are pointed to, are in main()'s "b_tmp". But there are no items
in your list yet, so you would be best to set a_tmp->bb = NULL.

> return a_tmp;
> }

> // ---------------- MAIN ----------------
>
> int main()
> {
> int nbb, naa;
> BB **BB_array;
> AA **AA_array;
> nbb = 0;
> naa = 0;
> BB_array = malloc(sizeof(BB **));
> AA_array = malloc(sizeof(AA **));

AA_array is a pointer to (an array of) POINTERS to AA.
At any point in time, you will have some number of pointers
in this array.

It looks as if you want to start off having one pointer-to-AA
in the array, so:

  AA_array = malloc( sizeof(AA *) );
  naa = 1;

Now there is a memory region capable of holding one pointer-to-AA,
and AA_array points to that region.

If, in future, you want to add another person at the end of the list:
  naa++;
  AA_array = realloc( AA_array, naa * sizeof(AA *) );
  AA_array[naa - 1] = createAA("new person");

Or to delete the last person:
  free( AA_array[--naa] );
  AA_array = realloc( AA_array, naa * sizeof(AA *) );

The 'realloc' function obtains a new block of memory in the size
you specify, and copies over the contents from the old block
(ie. you have changed the size of your array).

> char *name;
> name = malloc(50);

You allocate 50 bytes and point 'name' to it...
>
> /************************************************
> Q3) Do i have to malloc these arrays ?
> ************************************************/
>
> name = "Hello";

You point 'name' to "Hello", which is already sitting in memory
at a quite different place to the 50 bytes you just allocated. You
have now leaked the original 50 bytes, which have nothing pointing
to them any more.

> AA_array[naa++] = createAA(name, strlen(name));

It would have been be good design to keep 'naa's updating as close
as possible to the point where you allocate AA_array.

Simpler would have been:
    AA_array[0] = createAA("Hello");

>
> AA_array[0]->bb[AA_array[0]->n] = BB_array[0];
> /************************************************
> Q4) Can I do that ? Or do I have to malloc (before) again and again
> with something like :
> AA_array[0]->bb[AA_array[0]->n] = malloc(sizeof(B *));
> ************************************************/

I am guessing that you would want to make the chat-rooms(BB) maintain
a list of who(AA) is in it, and also have each person(AA) maintain
a list of which chat-rooms(BB) they are in. You could do this, but
it would involve quite a lot of work every time someone entered or
left a room.

If it were me designing this project, I would maintain a list
of pairs (AA *, BB *), indicating that person A is in room B,
rather than trying to store this information inside the
AA and BB objects.

>
> }
>
You have to go through the lists a_tmp and b_tmp, freeing each
member of them (and for each member, free its name; you probably
should have a function deleteAA() and deleteBB() to do this),
and then finally free a_tmp and b_tmp themselves. Although
you would get away with not freeing them (the OS will free all
memory your application allocated, when it exits).



Relevant Pages

  • Re: grow list by tail, pointer example recipe -- please comment
    ... manufacturing a pointer with that address. ... the next cons cell. ... believe these lists are in consecutive memory locations. ...
    (comp.lang.lisp)
  • Re: "Mastering C Pointers"....
    ... > If all the structs are part of a single object (e.g., ... For each pointer, cast it to char* and subtract the ... > details of how mallocallocates memory. ...
    (comp.lang.c)
  • Re: compile
    ... which allocates memory on a garbage-collected heap. ... which identifies some pointer or GCMalloc'd structure as ... in compilation with dummy arguments so as to fake a call to a routine ...
    (comp.lang.lisp)
  • Re: segfault w/ block, but not file scope
    ... >> int main ... When you define this pointer a file scope, ... allocates the necessary memory. ...
    (comp.lang.c)
  • Re: Can I Trust Pointer Arithmetic In Re-Allocated Memory?
    ... of the items from the bottom up of the buffer, ... write the two sorted lists to two new files. ... I worry that if I just supply a pointer to the first item ... The block of memory whose non-NULL address is returned from ...
    (comp.lang.c)

Loading