Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > memory allocation questions (newbie)

Reply
Thread Tools

memory allocation questions (newbie)

 
 
Severian
Guest
Posts: n/a
 
      07-03-2004
On Sat, 03 Jul 2004 08:26:56 +0200, /* frank */
<(E-Mail Removed)> wrote:

>Mike Wahler ha scritto:
>
>>int *p;
>>p = malloc(n * sizeof(int));

>
>But if malloc returns a void* , how this assignment
>is legal (force p that's a int* to a return value that it's void*) ?
>
>A bit confused?


By definition of the C standard, pointer-to-void can be converted to
pointer-to-anything (and vice versa). It makes perfect sense, and I'm
sure someone will chime in with chapter & verse.

--
Sev
 
Reply With Quote
 
 
 
 
/* frank */
Guest
Posts: n/a
 
      07-03-2004
Severian ha scritto:


> By definition of the C standard, pointer-to-void can be converted to
> pointer-to-anything (and vice versa). It makes perfect sense, and I'm
> sure someone will chime in with chapter & verse.


Then, since malloc returns a void*,
it should be done a cast.

int* p;
p = (int*) (malloc ( n * sizeof (int)));


Is it?









 
Reply With Quote
 
 
 
 
Peter Nilsson
Guest
Posts: n/a
 
      07-03-2004
"/* frank */" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Severian ha scritto:
> > By definition of the C standard, pointer-to-void can be converted to
> > pointer-to-anything (and vice versa).


A pointer to void can be implicitly converted to just about any other pointer (and vice
versa).

> > It makes perfect sense,


The decision to do this was quite deliberate. As to the sense of it... I won't go there.

> > and I'm
> > sure someone will chime in with chapter & verse.


6.3

> Then, since malloc returns a void*,
> it should be done a cast.


No. The implicit conversion of void* pointers was made to _avoid_ casts.

> int* p;
> p = (int*) (malloc ( n * sizeof (int)));
>
> Is it?


The idiom is precisely...

p = malloc(n * sizeof *p);

The cast is only required if you desire the code to be compilable as C++.

--
Peter


 
Reply With Quote
 
Malcolm
Guest
Posts: n/a
 
      07-03-2004

"Stephen Ramsay" <(E-Mail Removed)> wrote in message
>
> The use of malloc() in most of the books I've read make it sound pretty
> straightforward. If you allocate some memory (because the required
> amount of space isn't known until runtime), you have to free that space
> before the program ends.
>

The basics are simple. malloc() grabs a block of memory from somewhere and
gives you exclusive use of it. free() puts it back for re-use.
>
> 0. Let's suppose that I allocate space for p, but there are branches in
> the program that won't actually use p. Do I need to free the memory at
> every exit point? Or does the fact that this can happen indicate a bad
> design on my part?
>

Bad design. Usually each call to malloc() should be matched by one and only
one call to free().
>
> 1. Let's suppose that I pass p into a function. If that function is the
> last one that will ever need p, then presumably I can (and should) free
> it. But what if p is also used elsewhere? At a certain point, it seems
> like I would have to write some kind of reference counter . . .
>

Usually you solve this by freeing in the same block that you allocate in.
void foo(void)
{
char *ptr = malloc(N);

strcpy(ptr, "a string");

bar(ptr);

free(ptr);
}

void bar(char *ptr)
{
if(!strcmp(ptr, "That's all folks"))
{
bleep();
/* bad design here, free in foo */
free(ptr);
}

}
>
> 2. On a similar note, when I pass a pointer to some allocated memory
> as an argument to a function, pass it back out, pass it in somewhere
> else, aren't I always dealing with the same memory block? Will it not
> sufficeto release the memory after I'm done with all of this, or am I
> thinking about it incorrectly?
>

Yes. In C pointers pass about the address of the same physical block of
memory. However usually a function that receives a pointer to a data item
doesn't need to know whether it is allocated with malloc() or not.
>
> 3. Is there anything wrong with just freeing all allocated memory blocks
> at every exit point? I realize I might still have other sorts of
> problems, but wouldn't this prevent leakage?
>

It causes huge problems, because you can free memory twice, and you've got
to maintain every path. Sometimes you do need to have more than one matching
free() to each call to malloc(), but only rarely.

Lets take this example

struct tree
{
struct tree *child1;
struct tree *child2;
char data[32];
};

void treefunction(void)
{
struct tree *root = malloc(sizeof(struct tree));
root->child1 = 0;
root->child2 = 0;
strcpy(root->data, "root node");

buildthetree( root );

/* what do we do here ? */
}

void buildthetree(struct tree *root)
{
/* huge function that adds nodes to the tree, allocated with malloc() */
}

The answer is that we write a function

void deletetree(struct tree *root)
{
if(root->child1)
deletetree(root->child1);
if(root->child2)
deletetree(root-<child2);

free(root);
}

Now we call it from the function treefunction() to clean up.

We haven't quite managed to keep to the ideal of a call to malloc() followed
by a matching call to free() in the smae block, but we've come pretty close.
As long as the tree is built correctly the whole thing is controlled and the
chance of a memory leak slipping in is small.
>
> 4. What happens if I attempt to free memory that has already been
> freed?
>

It is undefined behaviour, which means anything can happen. Most likely the
computer would segfault or issue a "block corrupted" type warning. However
you could corrupt some vital data and send Mrs Bloggs an electricity bill
for 6 thousand million dollars.
>
> My apologies if all of this seems too basic for this list.
>

It's a very good question.


 
Reply With Quote
 
Malcolm
Guest
Posts: n/a
 
      07-03-2004

"Peter Nilsson" <(E-Mail Removed)> wrote in message
>
> No. The implicit conversion of void* pointers was made to _avoid_
> casts.
>

According to Plauger it was a hangover from the looser days of K and R C,
when there was no such thing as a void *, and retained to avoid breaking old
code.
>
> The cast is only required if you desire the code to be compilable as
> C++.
>

That's the main reason for keeping it in. Also to make it readable as C++
for someone who switches a lot between both languages.


 
Reply With Quote
 
Mac
Guest
Posts: n/a
 
      07-03-2004
On Sat, 03 Jul 2004 03:52:04 +0200, Nils O. Selåsdal wrote:

[snip]

> Just as as side note, most OS's deallocate dynamically allocated
> memory on process termination, thus no need for freeing things when
> exiting.


Right. You just want to make sure that you don't do something like this:

p=malloc(n * sizeof *p);

/* code which does not free p or assign its value to another variable */

p=malloc(m * sizeof *p);

That is a memory leak.

Mac

 
Reply With Quote
 
Herbert Rosenau
Guest
Posts: n/a
 
      07-04-2004
On Sat, 3 Jul 2004 06:26:56 UTC, /* frank */ <(E-Mail Removed)>
wrote:

> Mike Wahler ha scritto:
>
> >int *p;
> >p = malloc(n * sizeof(int));

>
> But if malloc returns a void* , how this assignment
> is legal (force p that's a int* to a return value that it's void*) ?


malloc is defined as a fuction returning a pointer to void. The C
standard says clearly that you can assign easy the value of a pointer
to void to a pointer of each type you needs really and you can even
use a pointer of each type in place when a pointer to void is
required. It is the C runtime that makes the conversion for you under
cover.

Each type above means clearly each type of data - not function as
function ponters can never converted to data pointers or the other way
around.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

 
Reply With Quote
 
Herbert Rosenau
Guest
Posts: n/a
 
      07-04-2004
On Sat, 3 Jul 2004 08:35:31 UTC, /* frank */ <(E-Mail Removed)>
wrote:

> Severian ha scritto:
>
>
> > By definition of the C standard, pointer-to-void can be converted to
> > pointer-to-anything (and vice versa). It makes perfect sense, and I'm
> > sure someone will chime in with chapter & verse.

>
> Then, since malloc returns a void*,
> it should be done a cast.
>
> int* p;
> p = (int*) (malloc ( n * sizeof (int)));
>
>
> Is it?


Never, really never. This will hide the most common mistake one can
ever do! Without a prototype in sight you will convert garbidge to to
garbidge when you tries to convert an int (that is what C assumes
malloc returns without the prototype in sight) to a pointer.

You knows: C says implicite a fuction without prototype in sight is a
fuction returning int. Many implementations use different locations
for return an int and return an pointer. So you cast fails to convert
something not set to something else, ignoring the return value from
malloc completely or at least partially.

NEVER, rreally NEVER use the cast operator (except you has double
checked the double check that you really KNOWS what you are doing.
castinng a pointer to void to anything else is ALWAYS a big mistake!
Whenever the compiler whines it whines because you are dumb enough to
use the result of malloc (or any other function that returns void*
without a prototype in sight. Correct the error using a unprototyped
function instead to make things with one hand. Use your head and
include the right header.


--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

 
Reply With Quote
 
Herbert Rosenau
Guest
Posts: n/a
 
      07-04-2004
On Fri, 2 Jul 2004 22:26:19 UTC, Stephen Ramsay <(E-Mail Removed)>
wrote:

> I'm wondering if someone can help me untangle some muddled thinking
> about memory allocation in C. I'm writing my first non-trivial app in
> C (and having a great time), but I'm finding it difficult to stamp out
> memory leaks.
>
> I'm sure most of what I'm about to say is wrong. I'd really be very
> grateful to know why.
>
> The use of malloc() in most of the books I've read make it sound pretty
> straightforward. If you allocate some memory (because the required
> amount of space isn't known until runtime), you have to free that space
> before the program ends.


Yes, that it's.

> The standard examples go something like this: You need to allocate space
> for an array of ints with n elements. When the program knows the value
> of n, you can allocate the memory like so:
>
> int *p;
>
> p = malloc(n * sizeof(int));
>
> (I understand from lurking on this list that p = (int *) malloc(n *
> sizeof(int)) is deeply offensive to many C fans
>
> When I'm done with that array, I need to free it like so:
>
> free(p);


correct.

>
> My way of describing this may not be too precise, but I think I
> understand this, and I've been able to use it this way in my programs
> without incident.
>
> However, I quickly run into problems the minute things get even slightly
> more complex. For example:
>
> 0. Let's suppose that I allocate space for p, but there are branches in
> the program that won't actually use p. Do I need to free the memory at
> every exit point? Or does the fact that this can happen indicate a bad
> design on my part?


Doesn't matter. You should allocate dynamic mememory at a point when
you knows you have to use it. Do so on the latest possible logical
point.
- initialise each pointer at creation time - in worst case
with NULL - when you have to create it some steps befor you
use it yet. This saves you weeks of debug time!
- allocate memory for a piece of data. That means one list member,
the whole array or whatever you needs now to work on.
- Initialise it; epically each pointer in it to have all pointer
alwways
in a clean, intitialised state (unused pointer shoulb be clearly
NULL,
not with random content!
- use it
- free it so soon as possible because your program is not the only one
that uses lots of memory. It may give unused memory free for use in
other applications.
- free it so soon as possible because your program may need
another bigger chunk immediately after the action is done.
It helps houseceeping memory accessible on the system and in your
app.
- assign NULL to each pointer and its sibilings when you have free'd
the
memory it points to (superflous only when the pointer itself will
go out of usage and visibility immediately after the free().
That means you allocs memory to a automatic pointer at startup of a
function
and frees it when the function goes straight to return to its caller
For pointers at file or extern scope you should ALWAYS assign NULL
to it
to have clean setup an unused pointer. So the program will crash
definitely
whenever it accesses it at an unwanted time. You can so even call
free()
multiple times without any problem because free(NULL) does
definitely nothing
whereas free(pointer to already free'd memory) invokes undefined
behavior.



> 1. Let's suppose that I pass p into a function. If that function is the
> last one that will ever need p, then presumably I can (and should) free
> it. But what if p is also used elsewhere? At a certain point, it seems
> like I would have to write some kind of reference counter . . .


Who says that this fuction is definitely the last one? Yeah, You may
still use a helper fuction to allocate memory for the action you are
starting up - and another helper that cleans the action up.

But whatever you do be sure that the logic your program is in any way:
- startup an action (open resources needed by that action)
when not all resources needed accessible: cleanup and exit action or
whole process
- work on the action
On error underway: don't forget to cleanup the resources
before you breaks either the action or the whole process.
- cleanup the action (close resources)

> 2. On a similar note, when I pass a pointer to some allocated memory as
> an argument to a function, pass it back out, pass it in somewhere else,
> aren't I always dealing with the same memory block? Will it not suffice
> to release the memory after I'm done with all of this, or am I thinking
> about it incorrectly?


Depends. Whenever you needs a resoure like files or memory:
- get it ready for use
- use it
- close/free it
- look ehat is to do next. (maybe you starts to use another set of
memory, files,...)

> 3. Is there anything wrong with just freeing all allocated memory blocks
> at every exit point? I realize I might still have other sorts of
> problems, but wouldn't this prevent leakage?


No. But it is ever better to free it immediately after it is truly
clear that there is no need for anymore. Whenever you starts again to
use it you starts from scratch - even when your program runs only
again through the same action.

> 4. What happens if I attempt to free memory that has already been freed?


You starts to go into undefined behavior like you does when you starts
to access it further. Anything can occure like:
- demons flying out of your nose
- the 3. world war starts up
- your home explodes
- your emplolyer will cash back the last 12 month salary from your
bank
- something else

Avoiding it is easy: assign NULL to the pointer you've free()d. So
even when you frees it again nothing happens. Or when you access it
now mistakenly the program will crash immediately. So debugging this
mistake gets easy.

Hint: to handle dynamic memory you should always test malloc() for
success! malloc returns NULL when it fails to deliver the requested
amount of memory.

Hint: sometimes it is more easy to use realloc than malloc() + copy
something + free the old location. But realloc() likes to fail like
malloc(). Assigning the result from realloc() to the same pointer you
give realloc for size change ends up in memory leak! Use a trmprary
pointer instead to store the result. Whenever realloc says that it has
resezed the mempory override the old pointer with the new one. When
realloc returns NULL the old memory (and the pointer points to) left
unchanged. It lefts then to you to do something with it and free() it
when anything is done.

Hint: It is mostenly a bad idea to exit() the program only because
malloc/realloc() fails! You have another resources open that needs a
defined cleanup (like write buffers, close files, free other
memory.....). Often you can recover easy from that error. Let the
higher level of your code decide what is to do in that case.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

 
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
An idea for heap allocation at near stack allocation speed Bjarke Hammersholt Roune C++ 14 03-06-2011 08:07 AM
static memory allocation versus dynamic memory allocation Ken C Programming 24 11-30-2006 12:37 AM
What is the difference between dynamic memory allocation,and stack allocation ? chris C++ 6 10-28-2005 05:27 AM
Dynamic memory allocation and memory leak... s.subbarayan C Programming 10 03-22-2005 02:48 PM
Memory allocation questions Eirik WS C Programming 3 02-08-2004 04:29 AM



Advertisments