[comp.lang.c] pointer allocation

xj01+@andrew.cmu.edu (Xue Jue) (12/19/88)

I am try to allocate a list of integer pointers by the following short program.
But for some reason, after I compiled it and tried to run, it gave me a
Segmentation fault message. I couldn't see what's wrong there. Could anyone out
there give me some guide?


#include <stdio.h>
int *(*B);

main()
{
 *B = (int *) calloc(18,sizeof(int));
}


By the way, this is on IBM RT work station. The same thing has been running on
IBM PC with microsoft C 5.0.

Thanks.

----jue xue

guy@auspex.UUCP (Guy Harris) (12/20/88)

 >I am try to allocate a list of integer pointers by the following short
 >program.  But for some reason, after I compiled it and tried to run,
 >it gave me a Segmentation fault message. I couldn't see what's wrong
 >there. Could anyone out there give me some guide?
 >
 >#include <stdio.h>
 >int *(*B);
 >
 >main()
 >{
 > *B = (int *) calloc(18,sizeof(int));
 >}

The statement "*B = <expression>" means "assign the value of the
<expression> to the object pointed to by 'B'".  "B" is implicitly
assigned a NULL pointer value by its declaration; therefore, it doesn't
point to anything.  As such, "assign the value of the <expression> to
the object pointed to by 'B'" is a meaningless command, since there *is*
no object pointed to by "B".

The RT PC presumably catches attempts to dereference NULL pointers, as
do several other C implementations.

Why did you not just do

	...
	int *B;

	main()
	{
		B = (int *) calloc(18, sizeof(int));
	}

evil@arcturus.UUCP (Wade Guthrie) (12/21/88)

You found yourself a stray pointer!

In article <8Xf3eSy00UkZ40cVE0@andrew.cmu.edu>, xj01+@andrew.cmu.edu (Xue Jue) writes:

> #include <stdio.h>
> int *(*B);

what you're doing here, is setting B up to be a pointer to a pointer to an int
so let's look at a <REALLY> simple model for what is going on in memory:

	variable	type			address		contents

	B		pointer to pointer	good1		garbage1
	(*B)		pointer to int		garbage1	garbage2
	(**B)		int			garbage2	garbage3

> main()
> {

Just an aside, you might declare calloc to return a pointer rather than
an int (default):
	char * calloc();	/* this'll help */

>	*B = (int *) calloc(18,sizeof(int));

When you do this, calloc allocates space for 18 ints somewhere in memory,
and passes this back to the thing to which B points.  Let's look at this
in two steps: 1) calloc allocates space for 18 ints

	variable	type			address		contents

	B		pointer to pointer	good1		garbage1
	(*B)		pointer to int		garbage1	garbage2
	(**B)		int			garbage2	garbage3

	(none)		int (18 of them)	good2		garbage4

And put that address (good2, in this case) into the thing to which B points:

	variable	type			address		contents

	B		pointer to pointer	good1		garbage1
	(*B)		pointer to int		garbage1	good2

	(**B)		int (18 of them)	good2		garbage4
> }

What you have succeeded in doing is putting an address at a garbage value
in memory (the address garbage1).  You need first to assign B to point to
something for which space has been allocated.  I find that memory maps
like these help to sort out what is going on.  The segmentation fault was
when you put something (in this case, the address good2) into a location
which was out of the legally addressable memory 

> By the way, this is on IBM RT work station. The same thing has been 
> running on IBM PC with microsoft C 5.0.

Maybe the IBM RT initializes variables to zero, making garbage1 actually 
NULL, and doesn't allow dereferencing a NULL pointer (a very wise practice, 
since it is non portable).  The IBM PC does not set variables to zero, so 
you were really corrupting the heap.  If your program was small, chances 
are that you would not see the error.  If this same program grew to the 
point where you were corrupting data and/or code, then the debugging job 
would be monsterous (because the bug would have been there since God 
invented dirt, but the places to look for bugs are the most recently 
written routines).
 

Wade Guthrie
Rockwell International
Anaheim, CA

(Rockwell doesn't necessarily believe / stand by what I'm saying; how could
they when *I* don't even know what I'm talking about???)

hermit@shockeye.UUCP (Mark Buda) (12/21/88)

In article <8Xf3eSy00UkZ40cVE0@andrew.cmu.edu> xj01+@andrew.cmu.edu (Xue Jue) writes:
>I am try to allocate a list of integer pointers by the following short program.
>But for some reason, after I compiled it and tried to run, it gave me a
>Segmentation fault message. I couldn't see what's wrong there. Could anyone out
>there give me some guide?
>
>
>#include <stdio.h>
>int *(*B);
>
>main()
>{
> *B = (int *) calloc(18,sizeof(int));
>}

Wow, a question I can answer, if not clearly (or correctly) :-)

Problem 1: You are allocating memory for 18 ints, not 18 pointers to ints.
	Try calloc(18,sizeof(int *));
Problem 2: If you were allocating memory for pointers to ints, you would
	want to cast the value returned by calloc to an (int **), not an (int *).
Problem 3: You are storing the pointer returned by calloc() in *B. This is
	very very bad. What you want is to store it in B. Storing it in *B puts
	it in the memory location B points to, and since B is never given a
	value, it doesn't really point anywhere useful. In fact, it is probably
	NULL. And as we all know, dereferencing a NULL pointer can mess up your
	day.

>By the way, this is on IBM RT work station. The same thing has been running on
>IBM PC with microsoft C 5.0.

Shows you something about the IBM PC... :-)
-- 
Mark Buda / Smart UUCP: hermit@shockeye.uucp / Phone(work):(717)299-5189
Dumb UUCP: ...rutgers!bpa!vu-vlsi!devon!shockeye!hermit
I hate this $%$@%!$@%!@$%@#$@!% machine.
"A little suction does wonders." - Gary Collins