access of memory beyond allocation, not causing segmentation fault...

S

sam_cit

Hi Everyone,

I have the following program unit,

#include <stdlib.h>

int main()
{
char *p = (char*)malloc(100);
if(p==NULL)
{
printf("...null...\n");
}
else
{
printf("...success...\n");
printf("1.%d\n",p[10]);
memset(p,0,101);
printf("2.%d\n",p[10]);
free(p);
printf("3.%d\n",p[101]);
}
}

I used gcc on Solaris OS and i get the following output,

1.0
2.0
3.0

Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

Thanks in advance!!!
 
I

Ian Collins

Hi Everyone,

I have the following program unit,

#include <stdlib.h>

int main()
{
char *p = (char*)malloc(100);
if(p==NULL)
{
printf("...null...\n");
}
else
{
printf("...success...\n");
printf("1.%d\n",p[10]);
memset(p,0,101);
printf("2.%d\n",p[10]);
free(p);
printf("3.%d\n",p[101]);
}
}

I used gcc on Solaris OS and i get the following output,

1.0
2.0
3.0

Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.
Nope, you just invoke the demons of undefined behavior.
 
M

Malcolm McLean

Hi Everyone,

I have the following program unit,

#include <stdlib.h>

int main()
{
char *p = (char*)malloc(100);
if(p==NULL)
{
printf("...null...\n");
}
else
{
printf("...success...\n");
printf("1.%d\n",p[10]);
memset(p,0,101);
printf("2.%d\n",p[10]);
free(p);
printf("3.%d\n",p[101]);
}
}

I used gcc on Solaris OS and i get the following output,

1.0
2.0
3.0

Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

Thanks in advance!!!
You need to compile with a bounds checking flag. Even then, you are not
guaranteed a segmentation fault because bounds checking doesn't work
perfectly.
 
R

Richard Bos

#include <stdlib.h>

int main()
{
char *p = (char*)malloc(100);

Don't cast malloc(). It is not necessary, should cause no problems with
a good compiler, and can hide errors. Also, unnecessary casts cause
conversion allergies in many programmers.
Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

No. Both cause undefined behaviour. Undefined behaviour is exactly that:
undefined. Nothing is defined about it. It may cause the compiler to
refuse to compile your program, if it can determine in advance that the
UB is guaranteed to be triggered; it may appear to work but actually do
nothing; it may crash with a segfault; it may write to or read from
random memory addresses; it may fire up your email program and send
lurid love-letters to General Musharraf. So don't do that.

Richard
 
S

sam_cit

#include <stdlib.h>
int main()
{
char *p = (char*)malloc(100);

Don't cast malloc(). It is not necessary, should cause no problems with
a good compiler, and can hide errors. Also, unnecessary casts cause
conversion allergies in many programmers.
Shouldn't the following statements cause a segmentation fault?
printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

No. Both cause undefined behaviour. Undefined behaviour is exactly that:
undefined. Nothing is defined about it. It may cause the compiler to
refuse to compile your program, if it can determine in advance that the
UB is guaranteed to be triggered; it may appear to work but actually do
nothing; it may crash with a segfault; it may write to or read from
random memory addresses; it may fire up your email program and send
lurid love-letters to General Musharraf. So don't do that.

Richard

But i think the statement, memset(p,0,101); will cause a memory
corruption for sure. And had someone been using that memory, it would
cause a problem for them.
Will memset() ever worry about the allocation or the owner of the
allocation, if i'm correct it would just set the specified memory
bytes with a specific value, isn't it?
 
M

Malcolm McLean

But i think the statement, memset(p,0,101); will cause a memory
corruption for sure. And had someone been using that memory, it would
cause a problem for them.
Will memset() ever worry about the allocation or the owner of the
allocation, if i'm correct it would just set the specified memory
bytes with a specific value, isn't it?
It depends on your system. A simple computer will just happily overwrite
memory, causing who knows what sort of malfunction. More modern systems
usually have some sort of low-level protection in place, so typically the
result will be a message saying "segmentation fault". However most systems
can't guarantee a segfault on buffer overrun.
 
M

Malcolm McLean

Richard Bos said:
Don't cast malloc(). It is not necessary, should cause no problems with
a good compiler, and can hide errors. Also, unnecessary casts cause
conversion allergies in many programmers.
Very arguable opinion presented as accepted practise and sage advice.
Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

No. Both cause undefined behaviour. Undefined behaviour is exactly that:
undefined. Nothing is defined about it.
No. The C standard defines nothing about it. That doesn't mean nothing is
defined about it elsewhere in the system.
 
C

Chris Dollin

Malcolm said:
Very arguable opinion presented as accepted practise and sage advice.

Let's see:

This is true: it's not necessary to cast the result of `malloc` to
assign it to a pointer variable.

This is true: it's legal code and doesn't have nasties in it.

This is true: if you forget to #include <stdlib.h>, and the
compiler doesn't say anything about implicit declaration of
functions, the cast will hide a pointer-to-int conversion,
which might be a convert-gibberish-in-int-register-to-gibberish-
in-pointer-register.

True by exhibition in this newsgroup.

I don't think your comment holds up.
Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

No. Both cause undefined behaviour. Undefined behaviour is exactly that:
undefined. Nothing is defined about it.
No. The C standard defines nothing about it.

That's right: that's what "undefined behaviour" means around here.
You've probably not read enough posts to notice.
That doesn't mean nothing is
defined about it elsewhere in the system.

It doesn't mean it is, either. (Accidents of implementation are not
definitions.)
 
R

Richard Bos

But i think the statement, memset(p,0,101); will cause a memory
corruption for sure.

Read the above again. Think about it thoroughly. Then realise that the
answer to your assumption is "this, too, is _undefined_".

Richard
 
K

Keith Thompson

Malcolm McLean said:
It depends on your system. A simple computer will just happily
overwrite memory, causing who knows what sort of malfunction. More
modern systems usually have some sort of low-level protection in
place, so typically the result will be a message saying "segmentation
fault". However most systems can't guarantee a segfault on buffer
overrun.

Such protection typically distinguishes between memory your program
owns and memory it doesn't. It's not able to protect against
overwriting other memory within your own program.

If you call memset(p, 0, 101), where p points to a 100-byte object,
the extra byte that gets clobbered will most likely be either
unallocated memory, or memory that's part of some other object, or
perhaps part of some system-specific bookkeeping data structure
(function return address, heap tracking data, etc.).

The behavior is undefined, so as far as the standard is concerned,
literally anything can happen. But the most likely result of going
*just barely* beyond the bounds of an object is that something within
your program will be corrupted; the symptoms may appear later or not
at all.
 
M

Malcolm McLean

Chris Dollin said:
Let's see:
You and Richard Bos give poweful reasons for losing the cast from malloc().
But for my point to fall, those who retain the cast would have to offer as
"no evidence" position.
As a little intellectual exercise, can you now list some good arguments for
casting malloc()?
It doesn't mean it is, either. (Accidents of implementation are not
definitions.)
This is sounding a bit like medieval philosophy. Accidentally segfaults but
inhering of no substance ...

You shouldn't try to draw too many conclusions about the fact that a
behaviour is undefined by the C standard, except to say that it is not a
correct C program, according to that standard.
 
R

Richard Heathfield

Malcolm McLean said:

As a little intellectual exercise, can you now list some good
arguments for casting malloc()?

No. I tried hard to think of even a single good reason, and failed. P J
Plauger, however, can give one good argument for *P J Plauger* casting
malloc.

<snip>
 
S

Stephen Sprunk

Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

They invoke undefined behavior, and the program/implementation is free to do
anything at/after that point _including doing nothing at all_. UB doesn't
mean you'll always get an error, just that your program is no longer
guaranteed to work (but it might, despite the UB -- at least until you
upgrade your compiler/OS, port to a new system, the phase of the moon
changes, etc.).

For _this particular scenario_, the most common result will be that your
program will continue to execute for a while as if you did nothing wrong,
then fail in a completely unrelated part of the code. The second most
common result will be that absolutely nothing will go wrong. The third,
only on particular implementations that do bounds-checking, will be some
sort of run-time error like you seem to expect.

(Most common systems don't do bounds-checking and only catch egregious abuse
of pointers. Most are also lazy about handing memory back to the OS, so you
can still access free()d memory for some period. It's not wise to rely on
these behaviors, however.)

S
 
M

Malcolm McLean

Richard Heathfield said:
Malcolm McLean said:



No. I tried hard to think of even a single good reason, and failed. P J
Plauger, however, can give one good argument for *P J Plauger* casting
malloc.
I was converted from malloc() casting to non-casting. However, as you say,
some very competent people do retain the cast.
 
R

Richard Heathfield

Malcolm McLean said:
I was converted from malloc() casting to non-casting. However, as you
say, some very competent people do retain the cast.

I only know of one competent person who retains the cast. P J Plauger.
 
¬

¬a\\/b

Shouldn't the following statements cause a segmentation fault?

printf("3.%d\n",p[101]);
//As i'm referring to p after the memory is deallocated
memset(p,0,101);
//As access to memory is beyond the allocated portion.

They invoke undefined behavior, and the program/implementation is free to do
anything at/after that point _including doing nothing at all_.

qui:
1) se p[101] e' memoria allocata per ragioni di allineamento tutto ok
2) altrimenti se p[101]==0 e si riscrive p[101]=0 tutto ok
3) altrimenti se p[101]!=0 e si scrive p[101]=0 la mia
implementazione di free vede l'errore e esce con il messaggio

ove "tutto ok"=="l'operazione non comporta niente di sbagiato"

in ogni caso nessun UB dipende solo da che cosa vi è scritto in p[101]
e del suo allineamento in memoria; tutto è determinato
UB doesn't
mean you'll always get an error, just that your program is no longer
guaranteed to work (but it might, despite the UB -- at least until you
upgrade your compiler/OS, port to a new system, the phase of the moon
changes, etc.).

For _this particular scenario_, the most common result will be that your
program will continue to execute for a while as if you did nothing wrong,
then fail in a completely unrelated part of the code.

qui:
1) o non succede niente
2) o free(p) si accorge che qualcosa non va nella struttura di
allocazione ed esce
 
R

Richard Heathfield

¬a\/b said:
qui:
1) o non succede niente
2) o free(p) si accorge che qualcosa non va nella struttura di
allocazione ed esce

Are you *trying* to get killfiled?

(Incidentally, you succeeded.)
 
B

Bart van Ingen Schenau

Richard said:
Malcolm McLean said:

I only know of one competent person who retains the cast. P J Plauger.
And even he does not advocate to cast the return value from malloc in
general.
To my knowledge, his reason for retaining the cast stems from such an
exceptional situation that it actually *confirms* the rule for not
casting the return value of malloc.

Bart v Ingen Schenau
 
M

Malcolm McLean

Bart van Ingen Schenau said:
And even he does not advocate to cast the return value from malloc in
general.
To my knowledge, his reason for retaining the cast stems from such an
exceptional situation that it actually *confirms* the rule for not
casting the return value of malloc.
One reason he gave was that ANSI permitted the implict cast. OK. I
surrender, _conversion_, reluctantly, and knowing that they were driving a
coach and horses through the type-checking system.
That seems a pretty general reason to me.
However it is only a stupid committee that can't even come up with a
standard anyone wants to implement, so that particular justification seems
rather weak.
 

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

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top