Hi all,
If I have a piece of code something like this
void main(void)
'void' is not a legal return type for main(), though many compilers do
their users a disservice by allowing it. Change it to int, and add a
corresponding 'return' statement down below.
{
char * p1="abcdefghijklmn";
.............................................
}
For p1 and whatever it points to , where is the memory allocated. Is
it on heap or stack or
some other common global area. I am assuming it should be either on
stack or some global area. Unless
a user does a malloc storage space cannot be allocated on heap is my
assumption. Can someone
throw some light on how compilers do this.
The memory is statically allocated. The result is roughly equivalent
to writing
int main(void)
{
static const char some_name[] = {'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '\0'};
char *p1 = (char*)some_name;
The actual location for such static memory is up to your compiler. As
usual, Twink has given you an answer that might be relevant to your
particular compiler, or it might be complete nonsense. The only way to
know for sure is to check your compilers' documentation, which would
have been a better answer than the one Twink gave you.
What if the above piece of code is changed to something like
void main(void)
{
char *p1;
char a[20]="abcdefgh";
strcpy(p1,a);
}
Now where is the space allocated for p1 and whatever it points to
after strcpy.
String literals are treated differently when they initialize char*
pointers than they are when they initialize char arrays. In the first
case, static memory is allocated for the contents of the string
literal, and the pointer is initialized with a value that points to
the first character of the array. It is not safe to attempt to write
to that array.
In the second case, the contents of the string literal are used to
directly initialize the declared array; no separate storage is
allocated. Whether or not the memory has static storage duration or
automatic storage duration depends upon the declaration of the array;
the same is true about whether or not the array is declared as
'const'.
In this case, both p1 and a are both allocated as memory with
automatic storage duration, which usually, but not necessarily, means
that it is allocated from a hardware stack. You'll need to check your
compiler's documentation to find out exactly how this is handled.
Each time a statement block is entered, objects defined in that block
with automatic storage duration need to be re-initialized. This isn't
an issue for your program, because it contains only one block which is
never reentered; the only such objects in your program could be
handled the same way as static memory, without causing any problems.
However, in the more general case this means that the information
needed to re-initialize the object each time the block is entered must
be stored somewhere else. The standard says nothing about how this
information is stored, and there are many different ways to do it. For
small objects, the data might even be stored as part of the
initialization instructions, rather than in a seperate block of
memory.
Now we come to the nasty part. p1 is uninitialized before the call to
strcpy(). As a result, the behavior of your program is undefined. In
principle, even attempting to read the value of p1 might make your
program abort, and there have been real machines where that would have
happened. In practice, what is likely to happen is that p1 contains a
bit pattern about which you know nothing, including whether or not it
represents a valid memory location. That pattern will be interpreted
as if it did represent a pointer, and that pointer value will be
passed to strcpy(). strcpy() will attempt to copy the string located
in 'a' to this unknown memory location. The consequences of doing so
could be catastrophic; on systems with poor memory protection, like MS/
DOS, it was actually possible to damage devices with a write to the
wrong memory location; it was certainly easy to mess up the
configuration of your computer, requiring at least a reboot. On more
modern OSs (a category that includes many OSs that predate MS/DOS by
decades), such code is like to produce a memory segment violation,
which will halt your program. If it doesn't halt, that means that p1
happens to point at a memory location that your program actually has
permission to write to, such as &p1. However, this will be an
unpredictable part of the memory allocated to your program, which
stands a good chance of making some other unpredictable part of your
program fail.
In short: NEVER use the value of an uninitialized variable; be
particularly careful about uninitialized pointer variables. You should
make sure that p1 points at something before you ask strcpy() to copy
something to the location p1 points at. You should also make sure that
whatever p1 points at, it is big enough to store the thing that you're
copying to it.