Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Newbie: learning to use malloc().

Reply
Thread Tools

Newbie: learning to use malloc().

 
 
Longfellow
Guest
Posts: n/a
 
      07-16-2006
I'm finally going to try to understand dynamic allocation of memory.
I've always just declared arrays (foo[xx]), but that's too limiting now.
I've looked at K&R2 (7.8.5 Storage Management: about 3/4 of a page, no
examples, just prototypes). D&D: half a page followed by some
warnings. C Traps and Pitfalls, and Expert C Programming: the standard
gotchas. And finally, comp.lang.c faq: a whole section on memory
allocation (7.x) with lots of wrong ways explained.

Nowhere that I can wrap my head around: clear examples of the Right Way
(tm). And, yes, I may well be in my *dense* period.

So this code:

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

int main (void)
{
char *buffer;

if ((buffer = malloc(80)) == NULL) return 1;
printf("sizeof buffer is %d\n", sizeof buffer);

free(buffer);

return 0;
}

It compiles and runs:
sizeof buffer is 4

If I insert code to read from stdin (using fgets), printing the input to
the screen yields exactly three characters (three plus '\0', I presume).

OTOH, if I 's/char *buffer;/char buffer[80];/', and delete the 'if ((...'
and 'free(...' lines, I get "sizeof buffer is 80".

Obviously, I'm clueless here. Would someone point me to a venue where a
knowledgeable person would be more than willing to patiently explain
enough of what I don't know so that I can bootstrap my knowledge with
practice? I hesitate to ask that here, but would be delighted if
someone would offer same!

Thanks for reading,

Longfellow

 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      07-16-2006
Longfellow wrote:
> I'm finally going to try to understand dynamic allocation of memory.
> I've always just declared arrays (foo[xx]), but that's too limiting now.
> I've looked at K&R2 (7.8.5 Storage Management: about 3/4 of a page, no
> examples, just prototypes). D&D: half a page followed by some
> warnings. C Traps and Pitfalls, and Expert C Programming: the standard
> gotchas. And finally, comp.lang.c faq: a whole section on memory
> allocation (7.x) with lots of wrong ways explained.
>
> Nowhere that I can wrap my head around: clear examples of the Right Way
> (tm). And, yes, I may well be in my *dense* period.
>
> So this code:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main (void)
> {
> char *buffer;
>
> if ((buffer = malloc(80)) == NULL) return 1;
> printf("sizeof buffer is %d\n", sizeof buffer);
>
> free(buffer);
>
> return 0;
> }
>
> It compiles and runs:
> sizeof buffer is 4
>
> If I insert code to read from stdin (using fgets), printing the input to
> the screen yields exactly three characters (three plus '\0', I presume).
>
> OTOH, if I 's/char *buffer;/char buffer[80];/', and delete the 'if ((...'
> and 'free(...' lines, I get "sizeof buffer is 80".
>

You are changing the type of buffer from a pointer to char to an array
of 80 char.

sizeof(char*) is 4 on your system and sizeof(char[80]) is 80.

Now's a good time to start using the standard return values from main,
EXIT_SUCCESS and EXIT_FAILURE.

Good luck!

--
Ian Collins.
 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      07-16-2006
Longfellow said:

<snip>
>
> It compiles and runs:
> sizeof buffer is 4
>
> If I insert code to read from stdin (using fgets), printing the input to
> the screen yields exactly three characters (three plus '\0', I presume).


When you use a fixed size array with fgets, the canonical technique is:

if(fgets(buf, sizeof buf, fp) != NULL)

C knows how big the array is, so that's fine.

But now that you're using a pointer into a dynamically allocated memory
block, you have to remember for yourself how big that block is.

size_t bufsize = 80;
char *buffer = malloc(bufsize * sizeof *buffer);
if(buffer != NULL)
{
if(fgets(buffer, bufsize, fp) != NULL)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
Longfellow
Guest
Posts: n/a
 
      07-16-2006
On 2006-07-16, Ian Collins <(E-Mail Removed)> wrote:

>You are changing the type of buffer from a pointer to char to an array
>of 80 char.


Yes, though actually the reverse. The array I understand, the pointer I
don't

>sizeof(char*) is 4 on your system and sizeof(char[80]) is 80.


Okay, here's a test program:

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

int main(void)
{
char *p;

printf("sizeof char is %d\n", sizeof(char));
printf("sizeof char * is %d\n", sizeof p);

return 0;
}

This yields:

sizeof char is 1
sizeof char * is 4

If I have this straight, sizeof char is defined as 1 byte, or so I have
often read. Standard does not guarantee this, IIUC; it's implementation
dependant?

sizeof a char * (character pointer?) is 4 bytes on this system (32 bit
processor?).

>Now's a good time to start using the standard return values from main,
>EXIT_SUCCESS and EXIT_FAILURE.


Yes, I use these already, although not in example code.

>Good luck!


Thank you!


On 2006-07-16, Richard Heathfield <(E-Mail Removed)> wrote:
> Longfellow said:
>
><snip>
>>
>> It compiles and runs:
>> sizeof buffer is 4
>>
>> If I insert code to read from stdin (using fgets), printing the input to
>> the screen yields exactly three characters (three plus '\0', I presume).

>
> When you use a fixed size array with fgets, the canonical technique is:
>
> if(fgets(buf, sizeof buf, fp) != NULL)


fgets with error checking?

> C knows how big the array is, so that's fine.


Yes, it does because it is specified in the parameter passed to fgets()?

> But now that you're using a pointer into a dynamically allocated memory
> block, you have to remember for yourself how big that block is.
>
> size_t bufsize = 80;
> char *buffer = malloc(bufsize * sizeof *buffer);
> if(buffer != NULL)
> {
> if(fgets(buffer, bufsize, fp) != NULL)
>

Okay, declaring and defining bufsize sets the stage for malloc() in the
same way that buffer[80] would do for an array?

Then the pointer to buffer is assigned a memory allocation of bufsize
multiplied by the size of a character pointer (here, *buffer). Ian
stated that a character pointer would be 4 bytes for my system, and the
little test program above verifies this. So malloc() is reserving 320
bytes?

I note the error checking above, and use it as a matter of course (it's
in the templates I've worked up).

Have I got it straight so far? If so, on to realloc() and calloc()...

Thanks for your lucid explanation, sir; yet another one and I appreciate it.

Longfellow

 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      07-16-2006
Longfellow wrote:
> On 2006-07-16, Ian Collins <(E-Mail Removed)> wrote:
>
>
>>You are changing the type of buffer from a pointer to char to an array
>>of 80 char.

>
>
> Yes, though actually the reverse. The array I understand, the pointer I
> don't
>
>
>>sizeof(char*) is 4 on your system and sizeof(char[80]) is 80.

>
>
> Okay, here's a test program:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> char *p;
>
> printf("sizeof char is %d\n", sizeof(char));
> printf("sizeof char * is %d\n", sizeof p);
>
> return 0;
> }
>
> This yields:
>
> sizeof char is 1
> sizeof char * is 4
>
> If I have this straight, sizeof char is defined as 1 byte, or so I have
> often read. Standard does not guarantee this, IIUC; it's implementation
> dependant?
>

sizeof char is always 1, the size of a byte isn't defined.

> sizeof a char * (character pointer?) is 4 bytes on this system (32 bit
> processor?).
>

Correct. It's possible, but unlikely that a pointer size isn't 32 bits
on a 32 bit CPU.
>
>>But now that you're using a pointer into a dynamically allocated memory
>>block, you have to remember for yourself how big that block is.
>>
>>size_t bufsize = 80;
>>char *buffer = malloc(bufsize * sizeof *buffer);
>>if(buffer != NULL)
>>{
>> if(fgets(buffer, bufsize, fp) != NULL)
>>

>
> Okay, declaring and defining bufsize sets the stage for malloc() in the
> same way that buffer[80] would do for an array?
>

No, it just enables you to remember the size of the buffer you have
allocated. It is also good style not to use so called magic numbers
like 80 in your code.

> Then the pointer to buffer is assigned a memory allocation of bufsize
> multiplied by the size of a character pointer (here, *buffer). Ian
> stated that a character pointer would be 4 bytes for my system, and the
> little test program above verifies this. So malloc() is reserving 320
> bytes?
>

NO! Notice Richard wrote "sizeof *buffer", that is the sizeof char.

--
Ian Collins.
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      07-16-2006
Longfellow said:

> On 2006-07-16, Ian Collins <(E-Mail Removed)> wrote:
>
>>You are changing the type of buffer from a pointer to char to an array
>>of 80 char.

>
> Yes, though actually the reverse.


Quite so.

> The array I understand, the pointer I don't


A pointer is just a value that refers to the location in memory of an object
or a function. In this case, it points to the lowest byte in a block of
memory that you allocated via malloc.

>
>>sizeof(char*) is 4 on your system and sizeof(char[80]) is 80.

>
> Okay, here's a test program:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> char *p;
>
> printf("sizeof char is %d\n", sizeof(char));
> printf("sizeof char * is %d\n", sizeof p);
>
> return 0;
> }
>
> This yields:
>
> sizeof char is 1
> sizeof char * is 4


Yes. Note that sizeof *p will be 1 in this case, since p points to a char.

> If I have this straight, sizeof char is defined as 1 byte, or so I have
> often read. Standard does not guarantee this, IIUC; it's implementation
> dependant?


The Standard guarantees that a char is exactly one byte in size, and it
further guarantees that a byte is at least 8 bits wide (although it may be
wider, and is wider on some systems).

<snip>

> On 2006-07-16, Richard Heathfield <(E-Mail Removed)> wrote:
>> Longfellow said:
>>
>><snip>
>>>
>>> It compiles and runs:
>>> sizeof buffer is 4
>>>
>>> If I insert code to read from stdin (using fgets), printing the input to
>>> the screen yields exactly three characters (three plus '\0', I presume).

>>
>> When you use a fixed size array with fgets, the canonical technique is:
>>
>> if(fgets(buf, sizeof buf, fp) != NULL)

>
> fgets with error checking?


Absolutely. What's the point in trying to get some data from a stream if you
can't tell whether you succeeded?

>> C knows how big the array is, so that's fine.

>
> Yes, it does because it is specified in the parameter passed to fgets()?


C knows how big the array is because you defined its dimension when you
defined the array itself. Yes, fgets knows how big the array is because you
told it.

>> But now that you're using a pointer into a dynamically allocated memory
>> block, you have to remember for yourself how big that block is.
>>
>> size_t bufsize = 80;
>> char *buffer = malloc(bufsize * sizeof *buffer);
>> if(buffer != NULL)
>> {
>> if(fgets(buffer, bufsize, fp) != NULL)
>>

> Okay, declaring and defining bufsize sets the stage for malloc() in the
> same way that buffer[80] would do for an array?


Well, no - it's just a handy way for your program to record the buffer size
without having hard-coded 80s all over the place. With a fixed-size array
you can use sizeof, but when you move to malloc, it still makes sense to
track the array size but sizeof won't tell you - it'll tell you the size of
the pointer instead - so you need to track it yourself. That's why I
introduced bufsize.

> Then the pointer to buffer is assigned a memory allocation of bufsize
> multiplied by the size of a character pointer (here, *buffer).


No, sizeof buffer would be the size of a character pointer; sizeof *buffer
is the size of the thing pointed to by buffer - i.e. the size of a single
char.

> Ian
> stated that a character pointer would be 4 bytes for my system,


Possibly he's right, but there's no point in relying on a particular size.
In any case, it's irrelevant; sizeof *buffer is 1, not 4, no matter how big
your pointers are.

> and the
> little test program above verifies this. So malloc() is reserving 320
> bytes?


No, 80 * 1 is 80, not 320.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
Bill Pursell
Guest
Posts: n/a
 
      07-16-2006

Longfellow wrote:

> Okay, here's a test program:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> char *p;
>
> printf("sizeof char is %d\n", sizeof(char));
> printf("sizeof char * is %d\n", sizeof p);
>
> return 0;
> }
>
> This yields:
>
> sizeof char is 1
> sizeof char * is 4



> Then the pointer to buffer is assigned a memory allocation of bufsize
> multiplied by the size of a character pointer (here, *buffer). Ian
> stated that a character pointer would be 4 bytes for my system, and the
> little test program above verifies this. So malloc() is reserving 320
> bytes?


No. Malloc reserved 80 bytes, but the address of that buffer
is 4 bytes in size. If you write:

char *p = malloc(sizeof *p * 80); /* you get 80 bytes*/
char *q = malloc(sizeof q *80); /* get 320 bytes*/

Usually, you want the first. In fact, doing the
second is really obfuscatory, since the malloc
implies that you are allocating
space for 80 pointers, rather than 80 chars.
Assigning that space to a char * rather than
a char ** is really confusing.

 
Reply With Quote
 
lovecreatesbeauty
Guest
Posts: n/a
 
      07-16-2006

Longfellow wrote:
> int main (void)
> {
> char *buffer;
>
> if ((buffer = malloc(80)) == NULL) return 1;
> printf("sizeof buffer is %d\n", sizeof buffer);


The code was evaluating the size of a pointer that was a link to the
space allocated. Use this one:
printf("sizeof buffer is %d\n", 80);

for that size was specified explicitly in literal. So why is it lost?

 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      07-17-2006
On 16 Jul 2006 08:24:35 -0700, "lovecreatesbeauty"
<(E-Mail Removed)> wrote:

>
>Longfellow wrote:
>> int main (void)
>> {
>> char *buffer;
>>
>> if ((buffer = malloc(80)) == NULL) return 1;
>> printf("sizeof buffer is %d\n", sizeof buffer);

>
>The code was evaluating the size of a pointer that was a link to the
>space allocated. Use this one:
> printf("sizeof buffer is %d\n", 80);
>
>for that size was specified explicitly in literal. So why is it lost?


Why is what lost? Nothing was lost. The fact that 80 bytes were
requested is not an attribute of buffer but of the call to malloc.
malloc does not return anything other than an address.


Remove del for email
 
Reply With Quote
 
Longfellow
Guest
Posts: n/a
 
      07-17-2006
On 2006-07-16, Bill Pursell <(E-Mail Removed)> wrote:
>
> Longfellow wrote:

<snip all>

Okay, thanks all for this thread, which is now a text file I can study.

Obviously, there's a lot of background I need to assimilate. With this
as a context, I'll dive back into K&R2 once again. The "point" seems to
be that I now need to differentiate pointers from arrays.

Next time I come back, I'll have a series of statements that reflect my
then current understanding. This is like debugging by reading compiler
errors: I introduce my "understanding" here, and you guys do the -Wall
-ansi -pedantic. When I get them past the last "NO! (whatever I don't
understand)", I'll write them up as part of my own tutorial for myself.


Somehow I doubt that there is any one text on the C language that even
approaches the usefulness of this forum, for which I thank you all once
again.

Longfellow

 
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
[I'm learning C]: Learning to use ucontext Andrey Popp C Programming 5 01-31-2012 01:05 AM
Learning to use wxPython KDawg44 Python 2 04-27-2007 06:05 PM
learning to use Canon 5D CNN_news Digital Photography 24 03-26-2006 02:59 PM
Learning C and Learning Make/Configure/Building/Linking Hal Vaughan C Programming 7 03-21-2006 05:07 PM
e-learning, (collaborative learning environment) collinm Java 1 09-08-2005 09:52 PM



Advertisments