Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Question about memory allocation??

Reply
Thread Tools

Question about memory allocation??

 
 
sethukr@gmail.com
Guest
Posts: n/a
 
      12-14-2006
Hi everybody,

While running the following program in GCC, i'm very much screwed.

main()
{
char *ptr1;
char arr[1];
int i;
char *ptr2;

ptr1 = (char *)malloc(1);
ptr2 = (char *)malloc(1);


printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
like, 000053

printf("\n address of arr : %u\n", arr); /* shows 000052

printf("\n address of i : %u\n", &i); /* shows 000045

printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
}

**Why the memory is allocated from bottom to top?? ( in the order
ptr2, i , arr, and ptr1)

**Integer takes only 4-bytes, it occupies 000045 to 000048.

**What happened to the memory between 000049 to 000051 here??

Can anybody tell me why this magic is happened??

Thanks in advance,
Sethu

 
Reply With Quote
 
 
 
 
=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=
Guest
Posts: n/a
 
      12-14-2006
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Hi everybody,
>
> While running the following program in GCC, i'm very much screwed.


That's not possible. You compile your program with GCC, you run it in
whatever operating system you are using.

> main()


Old-style definition. Better to be explicit: int main(void)

> {
> char *ptr1;
> char arr[1];
> int i;
> char *ptr2;
>
> ptr1 = (char *)malloc(1);
> ptr2 = (char *)malloc(1);


Don't cast malloc's result unless you know what you're doing. You
don't. The proper way to get rid of the warning that you get without it
is to include <stdlib.h>.

> printf("\n & ptr1 : %u\n", &ptr1);


If you use printf, you need a proper prototype. Include <stdio.h>.
After fixing that, %u is the format specifier for unsigned int. It is
not the format specifier for any type of pointer. The way to print
pointers is to convert them to void *, and then use printf's %p format
specifier.

> /* I got outputs
> like, 000053


/* comments require a matching */.

> printf("\n address of arr : %u\n", arr); /* shows 000052
>
> printf("\n address of i : %u\n", &i); /* shows 000045
>
> printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
> }
>
> **Why the memory is allocated from bottom to top?? ( in the order
> ptr2, i , arr, and ptr1)


Because that is the way your operating system works. As for why your
operating system works that way, it could be because that happens to be
the most efficient method for your processor type, it could be for
compatibility with other systems, it could be because it was easier to
implement, or it could be for any number of other reasons.

> **Integer takes only 4-bytes, it occupies 000045 to 000048.


It's possible but extremely unlikely that the addresses used are
actually 45 through 48. What's more likely is that you get misleading
output because you lied to the compiler. Do you get different addresses
with %p?

> **What happened to the memory between 000049 to 000051 here??


It's not used.

> Can anybody tell me why this magic is happened??


It's hardly magic. It's because your compiler decided it would be a
better idea to waste three bytes of memory than to deal with the
problems caused by using it. These problems vary from processor to
processor, and even from operating system to operating system, but
generally speaking, programs can crash or run much more slowly if the
compiler does not make sure variables of certain types are not stored
at specific addresses. Which types and which addresses are again
specific to your processor and operating system.

 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      12-14-2006
(E-Mail Removed) said:

> Hi everybody,
>
> While running the following program in GCC, i'm very much screwed.
>
> main()
> {
> char *ptr1;
> char arr[1];
> int i;
> char *ptr2;
>
> ptr1 = (char *)malloc(1);


Undefined behaviour: you forgot the prototype for malloc. See recent
comp.lang.c discussion in the thread entitled "malloc".

> ptr2 = (char *)malloc(1);
>
>
> printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
> like, 000053


Undefined behaviour: (a) you forgot the prototype for printf, and (b) you
gave a pointer value to printf when it was expecting an unsigned int. Each
of these is sufficient cause for the program to behave in any way
whatsoever.

> **Why the memory is allocated from bottom to top?? ( in the order
> ptr2, i , arr, and ptr1)


Why shouldn't it be?

> **Integer takes only 4-bytes, it occupies 000045 to 000048.
>
> **What happened to the memory between 000049 to 000051 here??


Compilers will often align pointers on boundaries that are multiples of a
given (typically small) integer.

> Can anybody tell me why this magic is happened??


When you break the rules of C, anything can happen.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
 
Reply With Quote
 
Chris Dollin
Guest
Posts: n/a
 
      12-14-2006
(E-Mail Removed) wrote:

> Hi everybody,
>
> While running the following program in GCC, i'm very much screwed.


I don't see why. ("Screwed" in this context usually means "it broke,
and this was a Very Bad Thing".)

> main()


`int main(void)` is preferred; and the `int` is /necessary/ for C99.

> {
> char *ptr1;
> char arr[1];
> int i;
> char *ptr2;
>
> ptr1 = (char *)malloc(1);


You should #include <stdlib.h> if you're mallocating. And the `(char*)` is
unnecessary (and unwise). I'd also use `malloc(sizeof(*ptr1))` because that's
part of a general safe pattern.

> ptr2 = (char *)malloc(1);
>
>
> printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
> like, 000053


You should #include <stdio.h> if you're printfing.

You were unlucky. `&ptr1` is a pointer value, not an integer: you
should use the `%p` format and cast to `(void*)` to ensure safe
portability.

Otherwise you get Undefined Behaviour: all bets about your code's
behaviour are off.

> printf("\n address of arr : %u\n", arr); /* shows 000052
>
> printf("\n address of i : %u\n", &i); /* shows 000045
>
> printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041


Dittoes.

> }
>
> **Why the memory is allocated from bottom to top?? ( in the order
> ptr2, i , arr, and ptr1)


Why not? The order of placement is the compiler's business. It can
allocate in whatever order it finds convenient. Maybe it's allocating
on a "stack" which "grows downwards". Who cares? [1]

> **Integer takes only 4-bytes, it occupies 000045 to 000048.
>
> **What happened to the memory between 000049 to 000051 here??


I expect it's been eaten by alignment issues.

> Can anybody tell me why this magic is happened??


This is C. There is /no magic/ (except as permitted by Undefined
Behavior).

The compiler will allocate local variables as convenient and
efficient as directed. Usually you don't need to care.

[1] /Some/ people care. Usually they're obliged to use some specific
implementation and know exactly why they care.

--
Chris "Perikles triumphant" Dollin
"We did not have time to find out everything we wanted to know."
- James Blish, /A Clash of Cymbals/

 
Reply With Quote
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      12-14-2006
(E-Mail Removed) <(E-Mail Removed)> wrote:
> While running the following program in GCC, i'm very much screwed.


Missing headers:

#include <stdio.h>
#include <stdlib.h>

> main()


Make that

int main( void )

> {
> char *ptr1;
> char arr[1];
> int i;
> char *ptr2;


> ptr1 = (char *)malloc(1);


Don't cast the return value of malloc() - it won't buy you anything
but will keep the compiler from complaining if you forgot to include
<stdlib.h>, which can result in ugly bugs on some platforms.

> ptr2 = (char *)malloc(1);


> printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
> like, 000053


The correct way to print pointers is to use "%p", used with the
pointer cast to a void pointer, e.g.

printf("\n & ptr1 : %p\n", ( void * ) &ptr1);

> printf("\n address of arr : %u\n", arr); /* shows 000052


> printf("\n address of i : %u\n", &i); /* shows 000045


> printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041


You forgot to return an int here as it is expected of main().

> }


> **Why the memory is allocated from bottom to top?? ( in the order
> ptr2, i , arr, and ptr1)


That memory isn't "allocated", at least not in the sense of
functions like malloc() etc. The compiler must make sure that
memory is available for local variables when the function is
called. How it does that is completely up to the implementation.
And the addresses of these variables can be wherever the compiler
likes them to be - it could even have different areas of memory
for ints, chars, pointers etc. (it also might "optimize out"
some of the local variables and just keep them in CPU registers).
If you plan to use some tricks because you believe you know how
your compiler is doing it, that's up to you, but you won't writ
C programs anymore that are portable - you're rather likely to
invoke undefined behaviour.

> **Integer takes only 4-bytes, it occupies 000045 to 000048.
> **What happened to the memory between 000049 to 000051 here??


That's strictly for the compiler to decide which also has to take
into account alignment issues.

> Can anybody tell me why this magic is happened??


The only way to find out about your compiler and the architecture
you're on (but mind, a different compiler will may do it differently,
and even the same compiler may do it differently when the program
gets compiled for a different arcitecture!) is to either read the
code for the compiler or ask its writers.

Regards, Jens
--
\ Jens Thoms Toerring ___ (E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
Kohn Emil Dan
Guest
Posts: n/a
 
      12-14-2006


On Thu, 14 Dec 2006, (E-Mail Removed) wrote:

> Hi everybody,
>
> While running the following program in GCC, i'm very much screwed.


>


You must #include <stdlib.h> if you want to use malloc()

> main()
> {
> char *ptr1;
> char arr[1];
> int i;
> char *ptr2;
>
> ptr1 = (char *)malloc(1);
> ptr2 = (char *)malloc(1);
>
>


The correct printf() format specifier for printing pointers is %p, not %u!

> printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
> like, 000053
>
> printf("\n address of arr : %u\n", arr); /* shows 000052
>
> printf("\n address of i : %u\n", &i); /* shows 000045
>
> printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
> }
>
> **Why the memory is allocated from bottom to top?? ( in the order
> ptr2, i , arr, and ptr1)
>


Because the C standard does not disallow this. Most likely it's easier for
the compiler to allocate variables this way if the machine uses a stack
that grows towards lower addresses. Try to understand that you cannot rely
on this in your programs. Even for gcc, passing different optimization
flags (e.g. -O3 (optimize for speed) vs -Os (optimize for space)) will
give different results.



> **Integer takes only 4-bytes, it occupies 000045 to 000048.
>
> **What happened to the memory between 000049 to 000051 here??
>


Perhaps the compiler decided that pointers have to be aligned at an
address which is a multiple of 4. Nowhere in the standard says that
variables have to be allocated one after the other, or even in the order
in which they are defined, and aligning variables in general results
better runtime performance.


> Can anybody tell me why this magic is happened??



The definite answer can be found by studying the gcc internals manual or
even better the gcc source.

>
> Thanks in advance,
> Sethu
>
>

Emil

 
Reply With Quote
 
Kenneth Brody
Guest
Posts: n/a
 
      12-14-2006
Chris Dollin wrote:
>
> (E-Mail Removed) wrote:

[...]
> > Can anybody tell me why this magic is happened??

>
> This is C. There is /no magic/ (except as permitted by Undefined
> Behavior).

[...]

Well, one could say that there is "magic", at least as far as the
application is concerned.

Q: How does free() know how much memory was allocated?
A: Magic.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <(E-Mail Removed)>

 
Reply With Quote
 
goose
Guest
Posts: n/a
 
      12-14-2006

Jens Thoms Toerring wrote:
> (E-Mail Removed) <(E-Mail Removed)> wrote:
>

<snipped>
>
> > printf("\n address of arr : %u\n", arr); /* shows 000052

>
> > printf("\n address of i : %u\n", &i); /* shows 000045

>
> > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041

>

<snipped>
>
> And the addresses of these variables can be wherever the compiler
> likes them to be - it could even have different areas of memory
> for ints, chars, pointers etc. (it also might "optimize out"
> some of the local variables and just keep them in CPU registers).


I'd be interested to know how an implementation plans to return
the address of a register.

goose,

 
Reply With Quote
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      12-14-2006
goose <(E-Mail Removed)> wrote:

> Jens Thoms Toerring wrote:
> > (E-Mail Removed) <(E-Mail Removed)> wrote:
> >

> <snipped>
> >
> > > printf("\n address of arr : %u\n", arr); /* shows 000052

> >
> > > printf("\n address of i : %u\n", &i); /* shows 000045

> >
> > > printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041

> >

> <snipped>
> >
> > And the addresses of these variables can be wherever the compiler
> > likes them to be - it could even have different areas of memory
> > for ints, chars, pointers etc. (it also might "optimize out"
> > some of the local variables and just keep them in CPU registers).


> I'd be interested to know how an implementation plans to return
> the address of a register.


If you take the address of a variable the compiler knows that it
can't "optimize out" the variable - but you usually don't print
out addresses, this was only done by the OP in order to find out
where the compiler puts the local variables.

Regards, Jens
--
\ Jens Thoms Toerring ___ (E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      12-14-2006
"(E-Mail Removed)" <(E-Mail Removed)> writes:
> While running the following program in GCC, i'm very much screwed.
>
> main()
> {
> char *ptr1;
> char arr[1];
> int i;
> char *ptr2;
>
> ptr1 = (char *)malloc(1);
> ptr2 = (char *)malloc(1);
>
>
> printf("\n & ptr1 : %u\n", &ptr1); /* I got outputs
> like, 000053
>
> printf("\n address of arr : %u\n", arr); /* shows 000052
>
> printf("\n address of i : %u\n", &i); /* shows 000045
>
> printf("\n & ptr2 : %u\n", &ptr2); /* shows 000041
> }


Here's a corrected version of your program:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *ptr1;
char arr[1];
int i;
char *ptr2;

ptr1 = malloc(1);
ptr2 = malloc(1);

printf("&ptr1 = %p\n", (void*)&ptr1);
printf("arr = %p\n", (void*)arr);
printf("&i = %p\n", (void*)&i);
printf("&ptr2 = %p\n", (void*)&ptr2);

return 0;
}

What I've done:

You're calling printf(), so the "#include <stdio.h>" is mandatory.
You're calling malloc(), so the "#include <stdlib.h>" is mandatory.

(Well, not *quite*; there are other ways to acheive the same
effect, but there's absolutely no point in using them. The
"#include" is the right way to do this.

Don't cast the result of malloc(). Doing so can mask certain errors,
such as omitting the required "#include <stdlib.h>" or incorrectly
using a C++ compiler to compile C code.

A good pattern for using malloc() is:

ptr = malloc(sizeof *ptr);

or, if you want to allocate an array:

ptr = malloc(COUNT * sizeof *ptr);

I've used the simpler "malloc(1)" here since you're only allocating a
single character (and sizeof(char) is 1 by definition). But if you're
going to be changing the code in the future, the lines:

ptr1 = malloc(1);
ptr2 = malloc(1);

should probably be written as:

ptr1 = malloc(sizeof *ptr1);
ptr2 = malloc(sizeof *ptr2);

The way to print a pointer value with printf is to convert it to void*
(one of the few cases where a cast is correct and necessary) and use
the "%p" format. The result of the "%p" format is
implementation-specific; it can be a number in hexadecimal, decimal,
octal, or even something other than a number. On the implementations
I use, it's a hexadecimal number corresponding to the representation
of the address. But remember that addresses *are not* numbers;
they're addresses.

I don't know why you called malloc(). You allocate one byte each for
ptr1 and ptr2 to point to, but you never use that allocated memory.
(You're printing the addresses of the pointer objects themselves,
*not* the addresses of what they point to.) If you are going to use
the allocated memory, you should *always* check the result of
malloc(); it returns a null pointer value on failure. (There's not
always a good way to handle this failure, but even aborting the
program with an error message is likely to be better than blindly
ignoring the problem.)

> **Why the memory is allocated from bottom to top?? ( in the order
> ptr2, i , arr, and ptr1)


Why not? Who cares?

It's the compiler's job to worry about where and how variables should
be allocated. It does this so you don't have to. It will allocate
local variables in whatever way the compiler's author decided made the
most sense. There may or may not be a consistent order. There may or
may not be gaps to allow for alignment. There *will* be a unique and
valid address for each declared variable, and that's really all you
need to know. If you write code that depends on the details of how
things are allocated, that code is non-portable, and it will break
when you try it with another compiler.

You're likely to find the comp.lang.c FAQ illuminating; it's an
excellent resource, thanks to a lot hard work by Steve Summit. It's
at <http://www.c-faq.com/>. Don't expect to be able to read the whole
thing in one sitting. If you like, you can start by reading bits and
pieces of it -- and you should always check it before posting a
question here.

But the FAQ is a set of answers to specific questions, not a tutorial.
You should also have a good book or other C tutorial. K&R2 (Kernighan
& Ritchie, _The C Programming Language_, 2nd edition) is generally
acknowledged to be the best tutorial, but it helps to have some
programming experience. For other resources, see the FAQ.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Patriot Memory PDC1G5600ELK Memory Review Silverstrand Front Page News 0 09-07-2005 02:24 AM
Differences between Sony Memory Stick & memory Stick Pro vs Memory Stick Duo? zxcvar Digital Photography 3 11-28-2004 10:48 PM
RAM Memory or virual memory Julián Sanz García ASP .Net 4 11-12-2004 06:25 PM
GC does not release memory...memory keeps growing!!! Mahesh Prasad ASP .Net 1 02-22-2004 08:40 AM
AspNet Process Memory Issue on Win2k Server - Peformance is fine - Memory usuage doesn't stop growing Cy Huckaba ASP .Net 1 06-26-2003 04:00 AM



Advertisments