behavior of free()

M

Mark

Hello

#include <stdlib.h>

int main(void)
{
int *i;

i = malloc(sizeof *i);
*i = 1;
free(i);
*i = 2;

return 0;
}

Compiling this with 'gcc' with just about every flags reasonably
possible, I don't get any warnings from compiler.

This code runs and doesn't crash, that surprises me. I expected that
referring to a pointer's contents after the pointer's memort was freed
would cause some 'special effects' on my system. Isn't this code
supposed to cause undefined behavior ?

Could you please explain why is it so? Thanks!

PS. Moreover even lint stays silent.
 
K

Keith Thompson

Mark said:
#include <stdlib.h>

int main(void)
{
int *i;

i = malloc(sizeof *i);
*i = 1;
free(i);
*i = 2;

return 0;
}

Compiling this with 'gcc' with just about every flags reasonably
possible, I don't get any warnings from compiler.

This code runs and doesn't crash, that surprises me. I expected that
referring to a pointer's contents after the pointer's memort was freed
would cause some 'special effects' on my system. Isn't this code
supposed to cause undefined behavior ?

Yes, it causes undefined behavior. Undefined behavior doesn't
mean that the program will crash; it means that the behavior
is undefined. Behaving in a seemingly benign manner is just one
possible consequence (and one of the worst, since it makes it more
difficult to track down the bug).

It's up to you, the programmer, to avoid undefined behavior.
The implementation *might* be able to help you in some cases,
but it's not required to, and you shouldn't depend on it.
 
T

Tim Harig

This code runs and doesn't crash, that surprises me. I expected that
referring to a pointer's contents after the pointer's memort was freed
would cause some 'special effects' on my system. Isn't this code
supposed to cause undefined behavior ?

It is not defined to crash any more then it is defined to do anyting else.
Special effects will only happen if the memory re-allocated to something
else before and after accessing it with i. For example, if you allocated
a second variable after freeing i:

int* i;
int* j;
i = malloc(sizeof(int*));
*i = 1;
free(i);
j = malloc(sizeof(int*));
*j = 2;
*i = 3;

then it is possible (but not guaranteed) that you might end up with a
situation where i and j point to the same place.

01:42,523$ cat test.c
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int* i;
int* j;

i = malloc(sizeof(int*));
*i = 1;
free(i);
j = malloc(sizeof(int*));
*j = 2;
*i = 3;

printf("%d", *j);

return 0;
}

01:42,524$ gcc -Wall -o test test.c

01:42,525$ ./test
3
01:42,526$

Then it is possible for 'special effects'; because, i would inadvertantly
point to j. If i is assigned in a loop using j as accounter for looping
through an array, then the loop may not get to the end of the array or it
could go passed the end clobbering memory somewhere else. I could also
end up pointing to somewhere in the middle of a structure or anywhere else.
Similar problems may be encountered by accessing i after it has been freed.
In all of these circumstances, i's dangling pointer could cause crashing
or 'special effects'; but, there is never a guarantee that it will do so.

Your program probably doesn't crash or cause any 'special effects' for
you simply because it is so small and exits before the dangling pointer
can cause too much trouble.
 
K

karthikbalaguru

It is not defined to crash any more then it is defined to do anyting else.
Special effects will only happen if the memory re-allocated to something
else before and after accessing it with i. For example, if you allocated
a second variable after freeing i:

int* i;
int* j;
i = malloc(sizeof(int*));
*i = 1;
free(i);
j = malloc(sizeof(int*));
*j = 2;
*i = 3;

then it is possible (but not guaranteed) that you might end up with a
situation where i and j point to the same place.

01:42,523$ cat test.c
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int* i;
int* j;

i = malloc(sizeof(int*));
*i = 1;
free(i);
j = malloc(sizeof(int*));
*j = 2;
*i = 3;

printf("%d", *j);

return 0;

}

01:42,524$ gcc -Wall -o test test.c

01:42,525$ ./test
3
01:42,526$

Then it is possible for 'special effects'; because, i would inadvertantly
point to j. If i is assigned in a loop using j as accounter for looping
through an array, then the loop may not get to the end of the array or it
could go passed the end clobbering memory somewhere else. I could also
end up pointing to somewhere in the middle of a structure or anywhere else.
Similar problems may be encountered by accessing i after it has been freed.
In all of these circumstances, i's dangling pointer could cause crashing
or 'special effects'; but, there is never a guarantee that it will do so.

Your program probably doesn't crash or cause any 'special effects' for
you simply because it is so small and exits before the dangling pointer
can cause too much trouble.

Exactly.

Karthik Balaguru
 
K

karthikbalaguru

Yes, it causes undefined behavior. Undefined behavior doesn't
mean that the program will crash; it means that the behavior
is undefined. Behaving in a seemingly benign manner is just one
possible consequence (and one of the worst, since it makes it more
difficult to track down the bug).

It's up to you, the programmer, to avoid undefined behavior.
The implementation *might* be able to help you in some cases,
but it's not required to, and you shouldn't depend on it.
Yes. Undefined behaviour can give either an undesired output
or a desired output. Hence it is called as undefined . It is not
healthy programming. As the size of the program grows, It can
cause problems that might take time to fix.

Karthik Balaguru
 
K

Kenny McCormack

Mark" said:
Compiling this with 'gcc' with just about every flags reasonably
possible, I don't get any warnings from compiler.

Is that you, Kiki?

Note that *somebody* must be generating this repetitive stream of "The
compiler didn't tell me something was wrong" posts. And a good thing it
is, too, since if we didn't have this stream, we'd run out of things to
talk about - and this newsgroup would die. Wouldn't want that, would we?
 
J

James Kuyper

karthikbalaguru said:
Yes. Undefined behaviour can give either an undesired output
or a desired output. Hence it is called as undefined .

The first statement is true but it's not the reason for the use of the
term "undefined". The term is used because the standard doesn't define
the behavior, it has nothing to do with whether or not the behavior is
desired.

Defined behavior is also capable of giving either a desired output or an
undesired one. For instance, if 'i' is the name of a variable with a
scalar type, the statement

i = 0;

has the defined behavior of setting the value of 'i' to 0 (or to a null
pointer if 'i' has a pointer type). Whether or not this is the desired
result depends entirely upon whether or not the developer actually
desired that this happen.

The difference between code with defined behavior and code with
undefined behavior is that in most cases it's possible to determine,
just by inspection of the code and a knowledge of the C standard,
whether the defined behavior is the same as the desired behavior; that
is not possible for code with undefined behavior.
 
S

Stephen Sprunk

Mark said:
Hello

#include <stdlib.h>

int main(void)
{
int *i;

i = malloc(sizeof *i);
*i = 1;
free(i);
*i = 2;

return 0;
}

Compiling this with 'gcc' with just about every flags reasonably
possible, I don't get any warnings from compiler.

This code runs and doesn't crash, that surprises me. I expected that
referring to a pointer's contents after the pointer's memort was freed
would cause some 'special effects' on my system. Isn't this code
supposed to cause undefined behavior ?

http://www.c-faq.com/ansi/undef.html

"undefined: Anything at all can happen; the Standard imposes no
requirements. The program may fail to compile, or it may execute
incorrectly (either crashing or silently generating incorrect results),
or it may fortuitously do exactly what the programmer intended.

Note, too, that since the Standard imposes absolutely no requirements on
the behavior of a compiler faced with an instance of undefined behavior,
the compiler (more importantly, any generated code) can do absolutely
anything. In particular, there is no guarantee that at most the
undefined bit of the program will behave badly, and that the rest of the
program will perform normally. "

Though not mentioned in the FAQ, there is also no requirement that the
compiler warn you about UB.

S
 
A

Anand Hariharan

(...)
The difference between code with defined behavior and code with
undefined behavior is that in most cases it's possible to determine,
just by inspection of the code and a knowledge of the C standard,
whether the defined behavior is the same as the desired behavior; that
is not possible for code with undefined behavior.

What is "desired behaviour" is rather tough to discern from "just by
inspection" of non-trivial code whose semantics are not obvious --
whether or not the code has defined or undefined behaviour. If you don't
believe me, take a look at some of the entries in ioccc.org ;-)

- Anand
 
D

dfighter

Kenny said:
Is that you, Kiki?

Note that *somebody* must be generating this repetitive stream of "The
compiler didn't tell me something was wrong" posts. And a good thing it
is, too, since if we didn't have this stream, we'd run out of things to
talk about - and this newsgroup would die. Wouldn't want that, would we?
If you don't want to see anymore posts in this newsgroup, there is a
much easier and faster way of achieving that than waiting for it to die
or trying to destroy it: simply unsubscribe.
Just a thought.
 
J

James Kuyper

Anand said:
(...)

What is "desired behaviour" is rather tough to discern from "just by
inspection" of non-trivial code whose semantics are not obvious --
whether or not the code has defined or undefined behaviour. If you don't
believe me, take a look at some of the entries in ioccc.org ;-)

You're right - what I should have said was, "just by inspection of the
code, a knowledge of the C standard, and a knowledge of what the desired
behavior is." The distinction between what a program actually does and
what the programmer wanted it to do is precisely the point I was trying
to make.
 
B

Boon

Mark said:
#include <stdlib.h>

int main(void)
{
int *i;

i = malloc(sizeof *i);
*i = 1;
free(i);

At this point, you might want to set i to 0 (if you're into defensive
programming, and don't mind the unnecessary overhead).

i = 0;
 
K

Kenny McCormack

If you don't want to see anymore posts in this newsgroup, there is a
much easier and faster way of achieving that than waiting for it to die
or trying to destroy it: simply unsubscribe.

Whatever give ya the notion that I don't enjoy the posts in this
newsgroup??? As I've posted many, many times: You can't make this stuff
up! You can't *buy* the kind of entertainment that you can get from
reading this NG.

Admittedly, there is always the question of whether it is entirely real
or not - i.e., if some of these posters, Kiki in particular, aren't, in
fact, very good performance artists. But, all in all, you might as well
assume it is all genuine. But either way, it should not be allowed to
detract from one's enjoyment.
Just a thought.

And not a very original one, at that.
 
R

Richard Bos

Boon said:
At this point, you might want to set i to 0 (if you're into defensive
programming, and don't mind the unnecessary overhead).

i = 0;

But do consider that this is like feeling safe because you added an
extra lock on your front door, but left the windows wide open.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top