next up previous Back to Operating Systems Home Page
Next: Additional Instructions (Assig. 1) Up: 1997 term messages Previous: Assig 1. To ASCII

Pointer allocation, a review

[ This is in reply to a fairly basic question about C. However, it seems
  that several people are stumbling on this same error, or very similar ones,
  so I thought it useful to forward my reply to the list. 
  Feel free to skip, you all veterans of C hack wars ;-)
]

  > I am having a big problem with with my program, I am trying to store all
  > the individual words of my file into an array, ( i.e. char **array)....
  > I allocated memory for this array of strings as follows...
  >
  >     array= (char**)malloc(word*sizeof(*str));
  >
  > word is the number of words to be stored, and *str is the pointer that
  > contains each individual word 

This call to malloc allocates an array composed of a number of cells equal to
"word", each large enough to contain one CHAR, not POINTER_TO_CHAR.  This
because if str is declared as:
        char *str;
then 
        a) str is a pointer variable: one large enough to contain the address
           of a character.
        b) *str is a character variable: the character whose address happens
           to be contained in str. 

hence sizeof(*str) is the size of one character. So the right way to
allocate the array is
        array = (char**)malloc(word*sizeof(char*));

Remember that sizeof can take for argument both a variable name and a 
type name (char*, in this case). 

Note also that the above malloc call allocates the needed to store
the POINTERS to the strings of the array, not the storage needed to 
store the strings themselves. In other words, after that malloc the
pointers point to nothing, and just contain garbage addresses.

  > ( i assume that every word in the file is less than 25 characters long)

AreYouSureAnAssumptionLikeThisMakesSense?PerhapsYouShouldReadAbout->fgets(3);
(gee, am I giving out one hint too many?
 ...and two more: strdup(3), strtok(3)  ;-)

  > the problem arises when I try to copy  *str into **array, I get a
  > segmentation error... i.e. the following line seems to screw me up
  > 
  >                      **array++ = *str;

Same error as before: an excess of *  on both sides.
Given the declarations:
        char **array, *str;
it follows that:
        *array and str are both of char* type, i.e. something that can 
           point to a string like "this", i.e. contain the address of
           the 't' in "this"
        **array and *str are of type char, i.e. something like 't' (-his);

So the "effect" of your expression above is to increment a character 
(e.g., 't' into 'u'), and then assign to it whatever str is pointing
to: probably garbage, in accordance to Murphy's Law.


\ Franco Callari