Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Malloc/Free - freeing memory allocated by malloc

Reply
Thread Tools

Malloc/Free - freeing memory allocated by malloc

 
 
CBFalconer
Guest
Posts: n/a
 
      09-21-2004
Peter wrote:
>
> Thanks everyone for replying, I will definitely "free" after each
> "malloc". Something strange is that after calls to "free", the
> linked list is still accessible, the values are still there.
> Should I also assign NULL value to each node?


Don't toppost. Your answer belongs after, or intermixed with, the
material you are quoting, after snipping away anything not germane
to your reply.

Having the 'values still there' is one valid form of undefined
behavior. Another is erasing your hard disk, or setting off
nuclear bombs. Don't do that.

--
"It is not a question of staying the course, but of changing
the course" - John Kerry, 2004-09-20
"Ask any boat owner the eventual result of continuing the
present course indefinitely" - C.B. Falconer, 2004-09-20


 
Reply With Quote
 
 
 
 
Dan Pop
Guest
Posts: n/a
 
      09-21-2004
In <(E-Mail Removed)> CBFalconer <(E-Mail Removed)> writes:

>Peter wrote:
>>
>> Thanks everyone for replying, I will definitely "free" after each
>> "malloc". Something strange is that after calls to "free", the
>> linked list is still accessible, the values are still there.
>> Should I also assign NULL value to each node?

>
>Don't toppost. Your answer belongs after, or intermixed with, the
>material you are quoting, after snipping away anything not germane
>to your reply.


Nope, he did the right thing. The rule has exceptions, but you need to
engage your brain to detect them.

His text was not directly related to anything he quoted, so there
was no point in not top posting. The quoted material was only
providing background context for those joining the thread at that
particular point and was of no interest for the other participants
to the discussion. No need to go again over it in order to find the
new stuff.

The ultimate proof that he did the right thing is the fact that you
didn't have to reformat his post in order to provide a meaningful reply:
all the included text could be deleted with one editor command, because
it was irrelevant to your answer.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: http://www.velocityreviews.com/forums/(E-Mail Removed)
Currently looking for a job in the European Union
 
Reply With Quote
 
 
 
 
Jason Curl
Guest
Posts: n/a
 
      09-22-2004
http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de wrote:
> Peter <(E-Mail Removed)> wrote:
>
>>Thanks everyone for replying, I will definitely "free" after each
>>"malloc". Something strange is that after calls to "free", the linked
>>list is still accessible, the values are still there. Should I also
>>assign NULL value to each node?

>
>
> Memory may still be accessible via the pointer and it may even still
> hold what it did before you called free(). But that's by pure chance,
> what the pointer was pointing to may also have become inaccessible or
> the memory it's pointing to may contain some other data. You simply
> can't know and using the pointer after free() invokes undefined beha-
> vior, i.e. everything can happen. So be very careful never to do that.
>
> If setting the pointer to NULL after the call of free() helps you in
> not using the pointer anymore then set it to NULL - but you don't
> have to zero out the memory before free()ing it, that would just be
> a waste of time. Setting the pointer to NULL is not required - all
> you must do is refrain from using that pointer for anything at all
> (including even just looking at its value).
>
> int *x = malloc( 100 * sizeof *x );
> ....
> free( x );
>
> Both the following lines would invoke undefined behavior.
>
> printf( "%d %d\n", x[ 11 ], *( x + 42 ); /* wrong! */
> printf( "%p\n", ( void * ) x ); /* wrong! */


I have a question about this particular line, printing the value of 'x'.
Why is this wrong? The memory allocated by x is on the function stack,
and I didn't believe you are accessing any invalid memory region?

Sure, I don't really see a point in accessing x, unless you have a
complex datastructure and you wish to free the memory, and then set
everything that was assigned to 'x' to NULL (even that can be avoided, I
only wanted to provide an example).

For example, I can see a malloc library for debugging (e.g.
ElectricFence) complaining on the first line, but not the second.

>
> even though on some machines you might get away with doing that. All
> you're allowed to do with 'x' after calling free() on it is to assign
> a new value to it, e.g. by using a further call of malloc()
>
> x = mallod( 20 * sizeof *x );
>
> or setting it to NULL
> Regards, Jens

 
Reply With Quote
 
Jens.Toerring@physik.fu-berlin.de
Guest
Posts: n/a
 
      09-22-2004
Jason Curl <(E-Mail Removed)> wrote:
> (E-Mail Removed)-berlin.de wrote:
>> Both the following lines would invoke undefined behavior.
>>
>> printf( "%d %d\n", x[ 11 ], *( x + 42 ); /* wrong! */
>> printf( "%p\n", ( void * ) x ); /* wrong! */


> I have a question about this particular line, printing the value of 'x'.
> Why is this wrong? The memory allocated by x is on the function stack,
> and I didn't believe you are accessing any invalid memory region?


No, 'x' is obbviously not dereferenced in the second line, so no
memory is accessed that isn't owned by the program. But even
determining the address stored in the pointer after free() has
been called on it invokes undefined behavior. In the C89 standard
(or draft) you will find in the section where malloc() and free()
etc. are described the sentence

The value of a pointer that refers to freed space is indeterminate.

And later in the appendix, listing the circumstances under which
undefined behavior results, you have

The behavior in the following circumstances is undefined:

* The value of a pointer that refers to space deallocated by a call
to the free or realloc function is referred to ($4.10.3).

That means using the value of the pointer itself (which, of course,
is unchanged by the call of free()) and not what it is (or was)
pointing to. That was also quite a surprise for me when I first
learned about it

But it allows to write a conforming C compiler even on a machine
that e.g. has dedicated address registers and automatically checks
on loading an address into such a register if the address belongs
to the address space of the process and traps (e.g. kills the pro-
gram) if it doesn't (with an exception for the NULL pointer). If
on such a machine free()ed memory would be removed from the pro-
cesses address space the pointer would, after the call of free(),
be invalid in the sense that loading it into an address register
would trap, even though the content (i.e. the bits stored in the
pointer) didn't changed at all. But I haven't seen a machine yet
were that would happen, but my experience isn't very large in that
respect

> For example, I can see a malloc library for debugging (e.g.
> ElectricFence) complaining on the first line, but not the second.


ElectricFence (and probably also most of the other memory debuggers)
don't seem to check for the problem with the second line. I guess
that's using the value of a free()ed pointer isn't an issue on most
machines and checking for that could be rather difficult.

Regards, Jens
--
\ Jens Thoms Toerring ___ (E-Mail Removed)-berlin.de
\__________________________ http://www.toerring.de
 
Reply With Quote
 
Felipe Magno de Almeida
Guest
Posts: n/a
 
      09-22-2004
Dan Pop wrote:

> In <(E-Mail Removed) > (E-Mail Removed) (Peter) writes:
>
>
>>Thanks everyone for replying, I will definitely "free" after each
>>"malloc". Something strange is that after calls to "free", the linked
>>list is still accessible, the values are still there.

>
>
> If you can still access those addresses, it means that the freed memory
> still belongs to your program (it is available for further allocation).
> The free() function typically doesn't touch the contents of the memory it
> deallocates.
>
> However, there are implementations where, under certain conditions, the
> deallocated memory no longer belongs to the program. Trying to access
> the freed memory will crash your program.
>
>
>>Should I also assign NULL value to each node?

>
>
> What for? If you're concerned about security issues (you don't want your
> data to be available to whatever program might "inherit" the memory you
> have freed), don't worry: the operating system is supposed to clear the
> memory before allocating it to another program.
>
> Dan

I think it is not necessarily true, not all operating systems clear the
memory before allocating it to another program. Probably if he is really
concerned about security issues on his data that is freed he should
clear it before freeing, and even ask the SO to not let it go to its
swap space.

--
Felipe Magno de Almeida
UIN: 2113442
email: felipe.almeida@ic unicamp br, felipe.m.almeida@gmail com
I am a C, modern C++, MFC, ODBC, Windows Services, MAPI developer
from synergy, and Computer Science student from State
University of Campinas(UNICAMP).
To know more about:
Unicamp: http://www.ic.unicamp.br
Synergy: http://www.synergy.com.br
current work: http://www.mintercept.com
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      09-22-2004
In <cis5p3$7s5$(E-Mail Removed)> Felipe Magno de Almeida <(E-Mail Removed)> writes:

>Dan Pop wrote:
>
>> What for? If you're concerned about security issues (you don't want your
>> data to be available to whatever program might "inherit" the memory you
>> have freed), don't worry: the operating system is supposed to clear the
>> memory before allocating it to another program.
>>

>I think it is not necessarily true, not all operating systems clear the
>memory before allocating it to another program.


Concrete examples, please.

>Probably if he is really
>concerned about security issues on his data that is freed he should
>clear it before freeing, and even ask the SO to not let it go to its
>swap space.


Before calling exit() or returning from main(), do you also clear all the
statically allocated data? What about the sensitive information that
might be still existing in the stack segment, but your program can no
longer reach? What about the copy of the data that might be still
existing on the swap partition?

There is no point in attempting to do the OS job: it can do it better,
faster and more reliably.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
Currently looking for a job in the European Union
 
Reply With Quote
 
Michael Wojcik
Guest
Posts: n/a
 
      09-22-2004

[Posted only to comp.lang.c; my server doesn't carry alt.comp.lang.c.]

In article <cis5p3$7s5$(E-Mail Removed)>, Felipe Magno de Almeida <(E-Mail Removed)> writes:
> Dan Pop wrote:
>
> > What for? If you're concerned about security issues (you don't want your
> > data to be available to whatever program might "inherit" the memory you
> > have freed), don't worry: the operating system is supposed to clear the
> > memory before allocating it to another program.
> >

> I think it is not necessarily true, not all operating systems clear the
> memory before allocating it to another program.


While this is true (there has existed at least one operating
environment where memory was not cleared before being allocated to a
program), all operating systems which meet the Orange Book C2
security criteria, or a higher level, must have "object reuse"
protection, which includes such clearing of memory.

That means that most C programmers writing code for general-purpose
OSes will not have to worry about manually clearing memory, at least
for this purpose.

Of course, as we point out to people all the time on c.l.c, not all C
programs are written for general-purpose OSes. However, the subset
of conforming C implementations which provide malloc (ie either are
hosted, or provide it as an extension in a freestanding implementa-
tion), which have any "operating system" to speak of and support
multiple "processes" (so one can allocate memory freed by another),
and which also do not provide object reuse protection, is likely to
be quite small - and people working in it probably know who they are.

> Probably if he is really
> concerned about security issues on his data that is freed he should
> clear it before freeing, and even ask the SO to not let it go to its
> swap space.


If he's really concerned with the security of his data, he's looking
at a subject far too large and off-topic to discuss in comp.lang.c.
There's a wealth of research and commentary on this subject readily
available on the Internet; this is not the place to rehash a few bits
of it.

--
Michael Wojcik (E-Mail Removed)

Company Secretary Finance Manager
1) Half-grey haired executives.
2) Must be waist-deep in their field of activities.
3) Must be having the know-how and the do-how of the latest
developments in their respective fields.
-- from "Appointments Vacant" section of Business India


 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      09-23-2004
[posted only to comp.lang.c -- alt.comp.lang.c does not exist on
newsguy]

>(E-Mail Removed)-berlin.de wrote:

[after]
>> int *x = malloc( 100 * sizeof *x );
>> ....
>> free( x );
>>
>> Both the following lines would invoke undefined behavior.
>>
>> printf( "%d %d\n", x[ 11 ], *( x + 42 ); /* wrong! */
>> printf( "%p\n", ( void * ) x ); /* wrong! */


In article <news:cirjao$nn4$(E-Mail Removed)>
Jason Curl <(E-Mail Removed)> wrote:
>I have a question about this [second] line, printing the value of 'x'.
>Why is this wrong? The memory allocated [for] x is on the function stack,
>and I didn't believe you are accessing any invalid memory region?


Let me back things up a bit. Suppose instead of "int *x" or even
"int y", or "float z", I tell you only that I have four bytes in
memory that are set to 0x12, 0x34, 0x56, and 0x78 in sequence.

What is the value stored in this four-byte region? Is it 0x12345678?
Is it perhaps 0x78563412? Or could it even be something like
17378244361449504001963252426735616.0?

The answer is: it depends. Those four bytes are, as a 32-bit int,
the first value (0x1234567 on a SPARC or 680x0-based machine,
but the second (0x78563412) on an Intel x86-based machine. The
third (1.73782e34, or 7019017 * pow(2,91)) occurs if those four
bytes are meant to be interpreted as a 32-bit floating point number
on the x86.

Clearly, then, the value of some sequence of bytes depends on the
*interpretation* of that byte-sequence. The next question I would
like to ask, then, is this: How are the bytes making up a pointer
interpreted?

On many machines, they happen to be interpreted in precisely the
same way as some integer; but this is not the only possible
interpretation. Those who used the x86 in its early 80186 and
80286 incarnations should remember the "1-megabyte pointer", in
which the upper 16 bits represented the top 16 of the 20 bits of
the address, and the lower 16 bits represented the bottom 16 of
the 20 bits of the address, with those two values being summed:

real_20_bit_address = ((upper_16(ptr) << 4) + lower_16(ptr)) & 0xfffff;

(This means that any given physical address has lots of different
32-bit values that refer to it. This particular "feature" was the
source of a lot of problems and the term "pointer normalization".
It is also one reason that the C standards define "a < b" only for
pointers a and b into a single object, while "a == b" is defined
even if a and b point to different objects -- the equality operators
must normalize their pointers, while the relational operators are
allowed to compare only the offsets.)

Yet another interpretation was allowed on some varieties of the
x86, in which the upper 16 bits of the pointer were an index into
an (external) table, and the lower 16 bits were an offset to be
applied to the result of the table:

real_NN_bit_address = table[upper_16(ptr)] + lower_16(ptr);
/* more or less */

All of these interpretations -- and indeed almost any other
interpretation anyone can think of yesterday, today, or tomorrow
-- are allowed (but not required) by the C standard. The last of
the above, with the table-lookup step, happens to allow something
else the x86 did: the table need not contain just a "base address".
It can also contain a "valid" flag:

if (table[upper_16(ptr)].valid == 0)
throw_runtime_error("invalid address");
real_NN_bit_address = table[upper_16(ptr)].base + lower_16(ptr);

Now, all free() needs to do is contain, as one of its steps:

table[upper_16(ptr)].valid = 0;

and suddenly a bit pattern that *was* valid, before the call to
free(), is no longer valid. An attempt to print it, which used
to work, may now cause a runtime "invalid address" error.

The bit pattern has not changed. What changed is the external
table. The C standard allows this, and tells you -- the C programmer
-- not to attempt to use the value in x after passing that value
to free(), just in case free() cleared the table's "valid" bit.

Of course, as Jens wrote, you *are* allowed to overwrite x with a
new value, or with NULL. Any C compiler must make sure this works,
even if it has this kind of "valid/invalid table entry" action that
goes on with malloc() and free().

This is all part of a more fundamental issue, which C programmers
in particular should consider, because C has "C bytes" that can be
used to access hardware-level "representations" instead of
language-level "values". That issue is: the *representation* of
a value, and value itself, are different things. Values arise
through *interpretation* of some bit pattern (a "representation"),
and the process of interpretation can be quite complex. We see
this now, today, on conventional architectures, only in floating-point
numbers -- but in the past, we saw such things elsewhere. There
were good reasons for complicated interpretations for pointers,
and those reasons may well recur in the future.

["Methods of interpretation" are also the reason we see byte-order
issues in integers. If some entity takes a long string of bits
and breaks it up into groups of, say, 8 at a time, it is that entity
that chooses which order to put out the groups, and then to
re-assemble them for later re-interpretation as a larger group.
Any given machine may have its own method(s) for splitting and
combining to get 8-bit groups, but if you, as a C programmer, deal
in terms of (integral) *values*, and do your own splitting and
combining, *you* can control the results, rather than being at the
mercy of your machine(s).]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
Felipe Magno de Almeida
Guest
Posts: n/a
 
      09-23-2004
Dan Pop wrote:

> In <cis5p3$7s5$(E-Mail Removed)> Felipe Magno de Almeida <(E-Mail Removed)> writes:
>
>
>>Dan Pop wrote:
>>
>>
>>>What for? If you're concerned about security issues (you don't want your
>>>data to be available to whatever program might "inherit" the memory you
>>>have freed), don't worry: the operating system is supposed to clear the
>>>memory before allocating it to another program.
>>>

>>
>>I think it is not necessarily true, not all operating systems clear the
>>memory before allocating it to another program.

>
>
> Concrete examples, please.
>
>
>>Probably if he is really
>>concerned about security issues on his data that is freed he should
>>clear it before freeing, and even ask the SO to not let it go to its
>>swap space.

>
>
> Before calling exit() or returning from main(), do you also clear all the
> statically allocated data? What about the sensitive information that
> might be still existing in the stack segment, but your program can no
> longer reach? What about the copy of the data that might be still
> existing on the swap partition?
>
> There is no point in attempting to do the OS job: it can do it better,
> faster and more reliably.
>
> Dan

I know gpg has a lot of code to try to make it more secure wherever it
runs on, trying even to not let the OS to put its data on the swap, and
not all OSes must do it, if all do, better. And I agree with Michael
Wojcik that here is not the place for this discussion.

--
Felipe Magno de Almeida
UIN: 2113442
email: felipe.almeida@ic unicamp br, felipe.m.almeida@gmail com
I am a C, modern C++, MFC, ODBC, Windows Services, MAPI developer
from synergy, and Computer Science student from State
University of Campinas(UNICAMP).
To know more about:
Unicamp: http://www.ic.unicamp.br
Synergy: http://www.synergy.com.br
current work: http://www.mintercept.com
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      09-24-2004
In <civc6j$52n$(E-Mail Removed)> Felipe Magno de Almeida <(E-Mail Removed)> writes:

>I know gpg has a lot of code to try to make it more secure wherever it
>runs on, trying even to not let the OS to put its data on the swap, and


Does this prove *anything* at all?

>not all OSes must do it, if all do, better. And I agree with Michael
>Wojcik that here is not the place for this discussion.


Then why did you start it here in the first place?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
Currently looking for a job in the European Union
 
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
Re: How to check whether malloc has allocated memory properly in caseif malloc(0) can return valid pointer Gene C Programming 0 12-20-2010 05:33 AM
Dynamically Allocated Memory vs. Statically allocated Memory csnerd@gmail.com C++ 5 12-09-2004 01:44 AM
freeing allocated memory Curley Q. C Programming 7 04-30-2004 04:09 PM
freeing allocated memory binaya C Programming 11 10-19-2003 06:44 PM
some queries on freeing memory allocated using malloc Hassan Iqbal C Programming 3 09-25-2003 02:53 PM



Advertisments