By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,136 Members | 2,145 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,136 IT Pros & Developers. It's quick & easy.

use delete to destroy primitive/object types but memory is not freed

P: n/a
Hello,

This is a simple question for you all, I guess .
int main(){
double *g= new double;
*g = 9;
delete g;
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;
*g = 111;
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;
return 0;
}

The output:
4 8 8 9
4 8 8 111

Although I delete g, why is it that I can still use it and it references to
actual memory?

The same happens when creating and deleting object types with new and
delete!

Please dont answer with what you think but with what actually happens. If
you can point me to web sources I can read on this, it would have been
great!

Thank you in advance.
Regards,
jimjim
Nov 14 '05 #1
Share this Question
Share on Google+
30 Replies


P: n/a
jimjim <Fr*********@blueyonder.co.uk> spoke thus:
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl; Please dont answer with what you think but with what actually happens. If
you can point me to web sources I can read on this, it would have been
great!


(comp.lang.c++ is that way ----->)

Your post is off-topic for comp.lang.c. Please visit

http://www.ungerhu.com/jxh/clc.welcome.txt
http://www.eskimo.com/~scs/C-faq/top.html
http://benpfaff.org/writings/clc/off-topic.html

for posting guidelines and frequently asked questions. Thank you.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #2

P: n/a
jimjim <Fr*********@blueyonder.co.uk> spoke thus:
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl; Please dont answer with what you think but with what actually happens. If
you can point me to web sources I can read on this, it would have been
great!


(comp.lang.c++ is that way ----->)

Your post is off-topic for comp.lang.c. Please visit

http://www.ungerhu.com/jxh/clc.welcome.txt
http://www.eskimo.com/~scs/C-faq/top.html
http://benpfaff.org/writings/clc/off-topic.html

for posting guidelines and frequently asked questions. Thank you.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #3

P: n/a
jimjim wrote:

Hello,

This is a simple question for you all, I guess .
int main(){
double *g= new double;
[...]


Stop right there: The question just becaue non-simple
for us-all here in comp.lang.c. Perhaps it would be simple
for them-all over thar in comp.lang.c++. Tread carefully
as you cross the demilitarized zone.

--
Er*********@sun.com
Nov 14 '05 #4

P: n/a
jimjim wrote:

Hello,

This is a simple question for you all, I guess .
int main(){
double *g= new double;
[...]


Stop right there: The question just becaue non-simple
for us-all here in comp.lang.c. Perhaps it would be simple
for them-all over thar in comp.lang.c++. Tread carefully
as you cross the demilitarized zone.

--
Er*********@sun.com
Nov 14 '05 #5

P: n/a
I knew it was an easy question. I should have looked at a faq first.

The answer is at http://www.eskimo.com/~scs/C-faq/q7.21.html as Christopher
pointed out.

Thanks for the reply :-)

Nov 14 '05 #6

P: n/a

change new to malloc and delete to free and if you dont know the answer
visit http://www.eskimo.com/~scs/C-faq/q7.21.html as Christopher pointed
out.

Nov 14 '05 #7

P: n/a
This layout http://www.lysator.liu.se/c/c-faq/c-faq-toc.html of the faq in
the previous post is easier for us the newbies in C to locate the
questions/answers ;-)

Pay attention at the top of the page. There are link to faqs that are also
extremely interesting for newbies like us to read. Most of my questions are
there!! ftp://rtfm.mit.edu/pub/usenet/news.answers/C-faq/faq as well as this
pub/usenet/comp.lang.c/ and this ftp.uu.net (directory
usenet/news.answers/C-faq/ )
Nov 14 '05 #8

P: n/a
On Wed, 07 Apr 2004 21:11:52 GMT, "jimjim"
<Fr*********@blueyonder.co.uk> wrote:

change new to malloc and delete to free and if you dont know the answer
visit http://www.eskimo.com/~scs/C-faq/q7.21.html as Christopher pointed
out.

I'll tell you a secret: Eric does know the answer. When you're
off-topic, you're off-topic. Don't argue about it, just take the good
advice you are given.

Even if the simple substitution you propose actually worked (it
doesn't) there are still differences between C and C++ memory
allocation, and comp.lang.c++ is where you'll get the right answers,
reviewed by the right people.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #9

P: n/a
jimjim wrote:

This is a simple question for you all, I guess .

int main(){
double *g = new double;
double* g = (double*)malloc(sizeof(double));
*g = 9;
delete g;
free((void*)g);
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;
fprinf(stdout, ...
*g = 111;
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;
fprintf(stdout, ...
return 0;
} The output:

4 8 8 9
4 8 8 111

Although I delete g,
why is it that I can still use it and it references to actual memory?

The same happens
when creating and deleting object types with new and delete!

Please don't answer with what you think but with what actually happens.
If you can point me to web sources I can read on this,
it would have been great!
delete g;

or

free((void*)g);

delete's or free's the object to which g points.
g is still a valid [pointer] object
but the object to which it points is *not*.
Any reference to *g is *undefined* --
not defined by either the C or C++ standards
after *g is delete'd or free'd.
cat main.cc #include <iostream>

int main(int argc, char* argv[]) {
double* p = new double;
*p = 9;
delete p;
double* g = new double;
std::cout << sizeof(g) << ' ' << sizeof(double) << ' '
<< sizeof(*g) << ' ' << *g << std::endl;
*p = 111;
std::cout << sizeof(g) << ' ' << sizeof(double) << ' '
<< sizeof(*g) << ' ' << *g << std::endl;
return 0;
}
g++ -Wall -ansi -pedantic -o main main.cc
./main

4 8 8 9
4 8 8 111

Notice that, after *p is delete'd (free'd),
the storage be allocated for another object (*g in this case).

Nov 14 '05 #10

P: n/a
> hen you're off-topic, you're off-topic. Don't argue about it, just take
the good advice you are given.

I cant understand why if I am off topic an answer exists in the C-faq. Of
course for the C equivalent of the C++ code I provided in my original post.
Take few steps back and look at the bigger picture please (Dont take it that
I am trying to be "clever" now please)
Even if the simple substitution you propose actually worked (it doesn't)
int main(){
int *g= malloc(sizeof(int));
*g = 9;
free(g);
printf("%d %d %d %d\n",sizeof(g),sizeof(double),sizeof(*g),*g);
*g = 111;
printf("%d %d %d %d\n",sizeof(g),sizeof(double),sizeof(*g),*g);
return 0; }

The above substitution gives me the same results. Please why dont you try to
explain to me what exactly you mean? This is a typical phainomenon in
newsgroups; people having the knowledge to answer but provide cryptic
answers. If you are not to give a clear answer to my question, its better
not to answer at all!
there are still differences between C and C++ memory allocation, and

comp.lang.c++ is where you'll get the right >answers, reviewed by the right
people.

Can you please explain to me what is the case in C. This is again a genuine
question. I just want to learn!

Nov 14 '05 #11

P: n/a
ha, that was such a good example!!

Thank you :-)
Nov 14 '05 #12

P: n/a
"jimjim" <Fr*********@blueyonder.co.uk> wrote in message
news:uO*********************@news-text.cableinet.net...
Even if the simple substitution you propose actually worked (it
doesn't)
int main(){
int *g= malloc(sizeof(int));
*g = 9;
free(g);
printf("%d %d %d %d\n",sizeof(g),sizeof(double),sizeof(*g),*g);
*g = 111;
printf("%d %d %d %d\n",sizeof(g),sizeof(double),sizeof(*g),*g);
return 0; }
Do you mean *g to be an int or a double? Mixing types the way you've done
is not portable and will not work on at least one popular architecture.
The above substitution gives me the same results. Please why dont you try to explain to me what exactly you mean? This is a typical phainomenon in
newsgroups; people having the knowledge to answer but provide cryptic
answers. If you are not to give a clear answer to my question, its better
not to answer at all!


free() is not required to release memory immediately, nor is it required to
make that memory somehow inaccessible; on most implementations it's
impossible to do that at the granularity of a single int. For example, on
unix-like systems it's common that memory can only be requested from or
released to the OS in page-sized (typically 4kB) blocks and release must be
done in LIFO order.

Accessing freed memory explicitly causes Undefined Behavior, which may in
most cases do what you expect it to do. Or it might not -- that's why it's
called "undefined".

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin
Nov 14 '05 #13

P: n/a
Stephen Sprunk wrote:
free() is not required to release memory immediately
nor is it required to make that memory somehow inaccessible;
on most implementations,
it's impossible to do that at the granularity of a single int.
For example, on unix-like systems it's common that
memory can only be requested from or released to the OS
in page-sized (typically 4kB) blocks
and release must be done in LIFO order.

Accessing freed memory explicitly causes Undefined Behavior,
which may in most cases do what you expect it to do.
Or it might not -- that's why it's called "undefined".


You're off-topic and out of your depth here.
The way that the OS acquires physical memory for processes
is transparent to allocating free storage in your C program.
The typical implementation of free storage is a free list
and it can and often does allow the program to allocate and free
memory at the granularity of a single int.
My GNU C compiler, for example, does this.

Nov 14 '05 #14

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
jimjim wrote:
This is a simple question for you all, I guess .
int main(){
double *g = new double;
double* g = (double*)malloc(sizeof(double));
*g = 9;
delete g;


free((void*)g);
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;


fprinf(stdout, ...
*g = 111;
cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl;


fprintf(stdout, ...
return 0;
}


What a mess. Try this:

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

int main(void)
{
double *g = malloc(sizeof *g);

*g = 9;
free(g);

printf("sizeof g = %d, sizeof(double) = %d, sizeof *g = %d\n",
(int)sizeof g, (int)sizeof(double), (int)sizeof *g);
*g = 111;

/*
* Note: There's no much point in repeating the printf;
* there's no way the sizes can change.
*/
printf("sizeof g = %d, sizeof(double) = %d, sizeof *g = %d\n",
(int)sizeof g, (int)sizeof(double), (int)sizeof *g);

return 0;
}

When I run this, I get:

sizeof g = 4, sizeof(double) = 8, sizeof *g = 8, *g = 9
sizeof g = 4, sizeof(double) = 8, sizeof *g = 8, *g = 111
delete's or free's the object to which g points.
g is still a valid [pointer] object
but the object to which it points is *not*.
Any reference to *g is *undefined* --
not defined by either the C or C++ standards
after *g is delete'd or free'd.


After the call to free(g), any reference to *g invokes undefined
behavior. Also, any reference to g, the pointer variable, invokes
undefined behavior, even if you don't dereference it. Although the
call to free() isn't going to change the bits that make up the value
of g, that value becomes invalid; even comparing g to another pointer
value invokes undefined behavior.

Of course, undefined behavior is a tricky thing; it can, and often
does, manifest itself as the program doing exactly what you think it
should. (Murphy's law, which is outside the scope of the C standard,
implies that it will then stop working at the most inconvenient
possible moment.)

After you've called free(g), you can assign a new value to g:

g = malloc(sizeof *g);
... /* g is now valid */
free(g);
... /* g is now invalid */
g = malloc(sizeof *g);
... /* g is now valid again */

This is allowed because it assigns a new value to g without referring
to the previous value.

C and C++ are two different languages, and we really can't discuss C++
here in comp.lang.c. If you want to discuss C++, feel free to do so
in one of the C++ newsgroups.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #15

P: n/a
jimjim wrote:
ha, that was such a good example!!

Thank you :-)


In the general case, following Trollsdale's example will only lead to
pain and sloppy code.

--
yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz
To email me, rot13 and convert spelled-out numbers to numeric form.
"Makes hackers smile" makes hackers smile.

Nov 14 '05 #16

P: n/a
Keith Thompson wrote:
After the call to free(g),
any reference to *g invokes undefined behavior.
Also, any reference to g, the pointer variable,
invokes undefined behavior, even if you don't dereference it.
Although the call to free() isn't going to change the bits
that make up the value of g,
It can't. g is passed by value.
that value becomes invalid;
That's meaningless.
even comparing g to another pointer value invokes undefined behavior.
Even if *g has not been free'd.
Of course, undefined behavior is a tricky thing;
it can, and often does, manifest itself
as the program doing exactly what you think it should.
No. Undefined behavior
is simply behavior not defined by the ANSI/ISO C [89]9 standard.
The behavior may be defined by the implementation,
the computer architecture, the operating system or some other standard.
(Murphy's law, which is outside the scope of the C standard,
implies that it will then stop working
at the most inconvenient possible moment.)
Not if the behavior is defined
by something besides the ANSI/ISO C [89]9 standard.

C is used to write platform specific applications such as
device drivers, operating system kernels and standard C libraries.
It is neither practical or desirable to comply
with the ANSI/ISO C standards in such applications.
After you've called free(g), you can assign a new value to g:

g = malloc(sizeof *g);
... /* g is now valid */
free(g);
... /* g is now invalid */
g = malloc(sizeof *g);
... /* g is now valid again */
But you said, "Also, any reference to g, the pointer variable,
invokes undefined behavior, even if you don't dereference it."

Doesn't

g = malloc(sizeof *g);

reference g?
This is allowed because it assigns a new value to g
without referring to the previous value.
That's not the same thing as "referencing g".
C and C++ are two different languages,
and we really can't discuss C++ here in comp.lang.c.
That's your opinion. You're welcome to it.
But I don't share it.
If you want to discuss C++,
feel free to do so in one of the C++ newsgroups.


That's religious intolerance. I don't share your bigotry.
If you don't want to discuss C++, please ignore all references to C++.
Just snip them out of your replies.

Nov 14 '05 #17

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
Keith Thompson wrote:
After the call to free(g),
any reference to *g invokes undefined behavior.
Also, any reference to g, the pointer variable,
invokes undefined behavior, even if you don't dereference it.
Although the call to free() isn't going to change the bits
that make up the value of g,
It can't. g is passed by value.


Right.
that value becomes invalid;


That's meaningless.


No, it isn't, though my use of the term "invalid" was somewhat
informal. Recall that g is a pointer to double. The call free(g)
causes the allocated double object (which can be referred to as *g) to
reach the end of its lifetime. C99 6.2.4p2 says:

The value of a pointer becomes indeterminate when the object it
points to reaches the end of its lifetime.

Attempting to refer to an indeterminate value causes undefined
behavior. (In most implementations, this won't actually cause any
problems, but the standard allows it to become a trap representation,
and referring to the pointer value could conceivably crash the
program. This would actually be sensible for a debugging
implementation.) In any case, there's no point in trying to refer the
value of a pointer after a call to free(); an attempt to do so
probably indicates a bug in the code.
even comparing g to another pointer value invokes undefined behavior.


Even if *g has not been free'd.


No, if free(g) hasn't been called, g can safely be compared for
equality to other pointer values. Some comparisons with <, <=, >, and= do invoke undefined behavior; perhaps that's what you were thinking of.
Of course, undefined behavior is a tricky thing;
it can, and often does, manifest itself
as the program doing exactly what you think it should.


No. Undefined behavior
is simply behavior not defined by the ANSI/ISO C [89]9 standard.
The behavior may be defined by the implementation,
the computer architecture, the operating system or some other standard.


And how does that contradict what I said? In any case, many instances
of undefined behavior are *not* defined by any other standard.
(Murphy's law, which is outside the scope of the C standard,
implies that it will then stop working
at the most inconvenient possible moment.)


Not if the behavior is defined
by something besides the ANSI/ISO C [89]9 standard.


You do know that Murphy's law is a joke, right?
C is used to write platform specific applications such as
device drivers, operating system kernels and standard C libraries.
It is neither practical or desirable to comply
with the ANSI/ISO C standards in such applications.
It is both practical and desirable to comply with the ISO standard as
much as possible (but no more than possible). It is neither practical
nor desirable to discuss the details of any platform-specific code in
this newsgroup; the people who can discuss it intelligently hang out
in platform-specific newsgroups.
After you've called free(g), you can assign a new value to g:
g = malloc(sizeof *g);
... /* g is now valid */
free(g);
... /* g is now invalid */
g = malloc(sizeof *g);
... /* g is now valid again */


But you said, "Also, any reference to g, the pointer variable,
invokes undefined behavior, even if you don't dereference it."


Yes. Perhaps I should have said any reference to the value of g.
Doesn't

g = malloc(sizeof *g);

reference g?


No. The operand of the sizeof operator is not evaluated (unless the
operand is a C99 variable length array, but that doesn't apply here).
The assignment doesn't refer to the value of g, it simply assigns a
new value.
This is allowed because it assigns a new value to g
without referring to the previous value.


That's not the same thing as "referencing g".


What's not the same thing? I can't tell whether you're agreeing or
disagreeing with me. By "referencing g", I mean "referring to (or
using) the value of g".
C and C++ are two different languages, and we really can't discuss
C++ here in comp.lang.c.


That's your opinion. You're welcome to it.
But I don't share it.


I presume you're referring to the second part of my statement; you
agree that C and C++ are two different languages, don't you?

Is it your opinion that the existing C++ newsgroups should be
abolished, and both languages should be discussed in the C newsgroups?
You're free to advocate that, but I don't think you'll have much luck.
If you want to discuss C++,
feel free to do so in one of the C++ newsgroups.


That's religious intolerance. I don't share your bigotry.
If you don't want to discuss C++, please ignore all references to C++.
Just snip them out of your replies.


Nonsense. If I don't want to discuss C++, I won't read the C++
newsgroups. If I do, I will. The consensus against discussing C++ in
comp.lang.c isn't about any dislike of the C++ language; for the most
part, it's because the regulars of comp.lang.c aren't able to provide
knowledgeable answers to questions about C++, or to correct errors in
other people's postings. That's *exactly* what comp.lang.c++ is for.

To the original poster (if you haven't given up by now): your original
question was about the new and delete operators, which are specific to
C++ and do not exist in C. You were advised to post your question in
comp.lang.c++, not because we were trying to get rid of you, but
because that's where to find the people who are able to answer
questions about new and delete. When you posted a revised question
about malloc() and free(), that was perfectly appropriate for
comp.lang.c, but it was a different question. malloc() and free() are
similar to new and delete, but they're not the same thing -- and I,
for one, am not competent to explain in detail what the differences
are. (If you're curious, comp.lang.c++ would be a good place to ask
about it, since C++ includes the C standard lirary. Be sure to check
the C++ FAQ first; it might already answer any questions you have.)

Some of us may seem abrupt at times (and sometimes some of us can be
downright rude) but for the most part we're sincerely trying to be
helpful -- even (or especially) when we advise you to go somewhere
else.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #18

P: n/a
Hi, I am still here :-)
Although the call to free() isn't going to change the bits
that make up the value of g, It can't. g is passed by value.

Right.


g is passed by value to free( ) and this is why it continues to have the
same value -pointing to the same memory location- after free( ) is called (I
hope I ve got it right). What may cause the pointer to assume an
indeterminate value?

free(g);
g = malloc(sizeof *g);

No. The operand of the sizeof operator is not evaluated (unless the
operand is a C99 variable length array, but that doesn't apply here).
The assignment doesn't refer to the value of g, it simply assigns a
new value.


I still cant understand this :-(

You said: "After the call to free(g) any reference to *g invokes undefined
behavior". I would have thought that as sizeof *g refers to/uses *g it may
invoke an undefined behavior. You said that the operator is not evaluated.
Can you elaborate please?

I presume you're referring to the second part of my statement; you
agree that C and C++ are two different languages, don't you?
If there was a standardised code of conduct for use in the comp.lang.c, it
would have definitely describe this as an inappropriate behaviour
(and who am I to judge you,e?)

To the original poster (if you haven't given up by now): your original
question was about the new and delete operators, which are specific to
C++ and do not exist in C.
This is true :-). I clicked on the wrong newsgroup.

However Robert was kind enough to convert my code in C and answer my
question in terms of C in which I am also interested in. I was wondering how
is it possible to free( ), dereference the pointer and still access the data
which I had assigned before. His example answered exactly this. Then Keith
told me that I should not refer to or dereference a pointer; it may cause an
undefined behaviour. The bottom line is that may and I have learned a lot -
which is the whole point of newsgroups- even though I posted my question to
the wrong newsgroup. There is no need for people to get upset and be rude.
This is what Robert wants to communicate.

I should also add that there are many like Robert in newsgroups. I have
seen questions that should have been posted to different newsgroup being
answered by people that happened to know the answer. I have also seen
questions that should have been posted to different newsgroup just being
ignored. I have also seen polite answers pointing out where one should ask
in order to find an answer to his/her question. I have also seen sarcastic,
inappropriate rude answers by people that consider themselves the
"fathers/guardians" of a new newsgroup. An answer reflects the quality of
ones character.
Some of us may seem abrupt at times (and sometimes some of us can be

downright rude)

There is no reason to be rude in newsgroups or even get upset by some
posts. The whole idea is openess, sharing of ideas, providing help,
co-operation, companionship......if one gets upset by some posts s/he may
consider to stop providing his/hers services to the newsgroup as there will
always be people just like myself that will unintetionaly post questions to
the wrong place and get them upset.

Nov 14 '05 #19

P: n/a
Keith Thompson wrote:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
Keith Thompson wrote:

.... snip ...
If you want to discuss C++,
feel free to do so in one of the C++ newsgroups.
That's religious intolerance. I don't share your bigotry.
If you don't want to discuss C++, please ignore all references
to C++. Just snip them out of your replies.


Nonsense. If I don't want to discuss C++, I won't read the C++
newsgroups. If I do, I will. The consensus against discussing
C++ in comp.lang.c isn't about any dislike of the C++ language;
for the most part, it's because the regulars of comp.lang.c aren't
able to provide knowledgeable answers to questions about C++, or
to correct errors in other people's postings. That's *exactly*
what comp.lang.c++ is for.

To the original poster (if you haven't given up by now): your
original question was about the new and delete operators, which
are specific to C++ and do not exist in C. You were advised to
post your question in comp.lang.c++, not because we were trying
to get rid of you, but because that's where to find the people
who are able to answer questions about new and delete. When you

.... snip ...
Some of us may seem abrupt at times (and sometimes some of us can
be downright rude) but for the most part we're sincerely trying
to be helpful -- even (or especially) when we advise you to go
somewhere else.


However ERT, popularly known as Trollsdale, is not one of those
helpful ones. His objective seems to be to impart misinformation,
sometimes subtly, sometimes crudely, and even sometimes interposed
between accuracies. You must never trust anything in his
messages, even if they appear to be quotes from others, because he
has the admirable habit of altering these to suit his
unmentionable taste and objectives.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #20

P: n/a
(On "free(g)")

In article <news:Zj*********************@news-text.cableinet.net>
jimjim <Fr*********@blueyonder.co.uk> writes:
g is passed by value to free( ) and this is why it continues to have the
same value -pointing to the same memory location- after free( ) is called (I
hope I ve got it right). What may cause the pointer to assume an
indeterminate value?
Have you ever used the low-level instructions on the 80x86 series
of CPUs? These have a mode of operation -- not used much if at
all today -- in which it really can happen.

Suppose the compiler implements passing the value of "g" via the
segment pointer ES combined with the data pointer EDI, for instance.
That is:

use(g);

compiles to (more or less):

mov g_segmet, %es
mov g_offset, %edi
call use

Now, for free(g) we get:

mov g_segmet, %es
mov g_offset, %edi
call free

Suppose that free() manipulates the segment table so that the value
in %es now refers to an invalid segment, then returns. If you then
attempt to call use(g), the "mov g_segment, %es" step will cause
a runtime trap. The bits in g_segment and g_offset have not changed,
but the "move g_segment into %es" register -- which used to be a
legal instruction sequence based on the segment table -- is now an
illegal instruction sequence, based on the now-changed segment
table.

(Nobody generates code like that today because it does not really
buy anything. It might help when debugging but it would run much
slower than simply not using the segment register.)

[On "operand of sizeof is not evaluated", so that sizeof *g is OK]
I still cant understand this :-(
The compiler *is* allowed to put g's segment into %es when you "use
the value" of g:

use(g); /* tries to load %es => trap */
p = g; /* for some reason, also tries to load %es */
*g = 3; /* again tries to load %es */

The compiler is *not* allowed to put g's segment into %es when you
write "sizeof *g":

x = sizeof *g; /* MUST NOT try to load %es */
[Someone] said: "After the call to free(g) any reference to *g
invokes undefined behavior". I would have thought that as sizeof
*g refers to/uses *g it may invoke an undefined behavior. You said
that the operator is not evaluated. Can you elaborate please?


It is just a quirk of the C standard, which says that sizeof never
evaluates its operand (except for some new VLA cases in C99).

If the C standard said "any variable named Zorg must always be
negative", then any variable named Zorg would always be negative.
There would be no fundamental reason; it would just be so.

There are a number of things in the C standard that I think are
wrong design decisions, but they are there and I have to put up
with them (or else not use Standard C). There are a number of
"right decisions" too, and some that I think are indifferent. It
is up to each individual (or corporation or whatever) to decide
whether to live with an existing standard, augment it with additional
standards, subtract from it, ignore it, etc.; but here in comp.lang.c
we generally talk only about Standard C.

"If the C standard says that the behavior depends on the phase of
the moon, the programmer should be prepared to look out the window
as necessary." --me :-)
--
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.
Nov 14 '05 #21

P: n/a
Chris Torek wrote:
(On "free(g)")

jimjim writes:
g is passed by value to free( ) and this is why it continues
to have the same value -pointing to the same memory location-
after free( ) is called (I hope I've got it right).
What may cause the pointer to assume an indeterminate value?

Have you ever used the low-level instructions
on the 80x86 series of CPUs? These have a mode of operation --
not used much if at all today -- in which it really can happen.

Suppose the compiler implements passing the value of "g" via the
segment pointer ES combined with the data pointer EDI, for instance.
That is:

use(g);

compiles to (more or less):

mov g_segmet, %es
mov g_offset, %edi
call use

Now, for free(g) we get:

mov g_segmet, %es
mov g_offset, %edi
call free

Suppose that free() manipulates the segment table
so that the value in %es now refers to an invalid segment,
then returns. If you then attempt to call use(g),
the "mov g_segment, %es" step will cause a runtime trap.
Can you demonstrate this "runtime trap"
with a function that "manipulates the segment table"?
The bits in g_segment and g_offset have not changed,
but the "move g_segment into %es" register --
which used to be a legal instruction sequence
based on the segment table --
is now an illegal instruction sequence,
based on the now-changed segment table.
If free() invalidates g by manipulating the segment table,
what prevents the invalidation of other pointers?

Your reasoning is fallacious because no implementation of free()
does not, in fact, manipulate the segment table
as you have hypothesized:

http://www.don-lindsay-archive.org/s...tml#hypothesis
(Nobody generates code like that today because it does not really
buy anything. It might help when debugging but it would run much
slower than simply not using the segment register.)
Implementation that did generate "code like that"
would compile Keith Thompson's example without complaint
and produce the same results.

[On "operand of sizeof is not evaluated", so that sizeof *g is OK]
I still can't understand this :-(
The compiler *is* allowed to put g's segment into %es
when you "use the value" of g:

use(g); /* tries to load %es => trap */
p = g; /* for some reason, also tries to load %es */
*g = 3; /* again tries to load %es */

The compiler is *not* allowed to put g's segment into %es
when you write "sizeof *g":

x = sizeof *g; /* MUST NOT try to load %es */

[Someone] said: "After the call to free(g) any reference to *g
invokes undefined behavior". I would have thought that as sizeof
*g refers to/uses *g it may invoke an undefined behavior. You said
that the operator is not evaluated. Can you elaborate please?


It is just a quirk of the C standard, which says that sizeof never
evaluates its operand (except for some new VLA cases in C99).


Is sizeof evaluated at compile-time or at run-time?
If the C standard said "any variable named Zorg must always be
negative", then any variable named Zorg would always be negative.
There would be no fundamental reason; it would just be so.

There are a number of things in the C standard that I think are
wrong design decisions, but they are there and I have to put up
with them (or else not use Standard C). There are a number of
"right decisions" too, and some that I think are indifferent.
It is up to each individual (or corporation or whatever)
to decide whether to live with an existing standard, augment it
with additional standards, subtract from it, ignore it, etc.;
but here in comp.lang.c we generally talk only about Standard C.

"If the C standard says that the behavior depends on the phase of
the moon, the programmer should be prepared to look out the window
as necessary." --me :-)


Are you advocating "blind faith" in the standards documents?

Nov 14 '05 #22

P: n/a
"jimjim" <Fr*********@blueyonder.co.uk> writes:
Hi, I am still here :-)
> Although the call to free() isn't going to change the bits
> that make up the value of g,
It can't. g is passed by value. Right.


g is passed by value to free( ) and this is why it continues to have the
same value -pointing to the same memory location- after free( ) is called (I
hope I ve got it right). What may cause the pointer to assume an
indeterminate value?


In C, the safest approach is to think of a pointer as an opaque
abstract entity that supports certain operations defined by the C
standard. If you happen to know something about how machine addresses
work in assembly language, that's great. 99% of the time a C pointer
will be implemented as a machine address, and operations on it will
work as you would expect. That knowledge can help you to understand
how C pointers work, and why they're defined as they are -- but the
language standard allows them to behave in ways that don't necessarily
match the "obvious" behavior of machine addresses.

A pointer object, like any object in C, has a value that can be viewed
as a sequence of unsigned bytes, and that can be displayed, for
example, in hexadecimal. There's no guarantee about what those bytes
are going to look like, but it can be instructive to examine them if
you want a more concrete example of how an implementation might work.

In the following program, I convert a pointer value to unsigned int
and display its value in hexadecimal. This happens to work as
"expected" on the platform I'm using, but don't count on this being
portable. The program assumes that it makes sense to display the
result in 8 hexadecimal digits; this happens to be true on the system
I'm using, but again, it's not guaranteed (there are plenty of systems
with 64-bit pointers, and other sizes are possible.)

#include <stdio.h>
#include <stdlib.h>
/*
* Warning: This program invokes undefined behavior.
*/
int main(void)
{
double *ptr;

ptr = malloc(sizeof *ptr);
*ptr = 9.25;
printf("After malloc(): ptr = 0x%08x, *ptr = %g\n",
(unsigned)ptr, *ptr);

free(ptr);
printf("After free(): ptr = 0x%08x, *ptr = %g\n",
(unsigned)ptr, *ptr);

*ptr = 111.125;
printf("After assignment: ptr = 0x%08x, *ptr = %g\n",
(unsigned)ptr, *ptr);

return 0;
}

When I compile and execute this program, it gives me the following
output:

After malloc(): ptr = 0x000209c0, *ptr = 9.25
After free(): ptr = 0x000209c0, *ptr = 9.25
After assignment: ptr = 0x000209c0, *ptr = 111.125

Now let's examine in a bit more detail what's going on here, both in
terms of the underlying hardware and in terms of the C language
standard.

The call to malloc() allocates memory space for a double object; we
assign the resulting address to the pointer object ptr. (In a
real-world program we'd want to check whether the malloc() call
succeeded, and probably bail out if it didn't.)

We then assign a value to the double object that ptr points to, and we
display (in a non-portable manner) the value of ptr and of what it
points to.

As it happens, pointers on the system I'm using are represented as
machine addresses (actually virtual addresses). malloc() allocated 8
(sizeof(double)) bytes of memory starting at address 0x000209c0.

The C runtime system has reserved that chunk of memory, guaranteeing
that it belongs to this program, that we can read and write it, and
that no other object overlaps it.

Now we call free(). By doing so, we're informing the runtime system
that we no longer need that chunk of memory, that we won't try to use
it again, and that the runtime system is now free to reallocate it for
other purposes. There's no guarantee about what the runtime system
will actually do with that chunk of memory; it could well remain
unused for the remainder of the execution of this program. Or it
could be immediately reallocated for use as temporary storage. By
calling free(), we're telling the runtime system that we don't care
what happens to that chunk of memory; we're done with it. (We're
*not* asking the runtime system to prevent us from trying to access it
again.)

But we still have the pointer value. Since free()'s argument is
passed by value, the variable ptr is referenced, but not modified. It
still contains the same bit pattern, 0x000209c0. (There's been some
debate about whether a sufficiently clever implementation might be
allowed to modify the value of ptr, but we'll assume that it can't.)

So what does 0x000209c0 mean? After the call to malloc(), it was the
address of a chunk of memory that we owned. After the call to free(),
in terms of the underlying hardware, it's still the address of the
same chunk of memory; the only difference is that it's memory that we
no longer own. The runtime system is free to do what it likes with
that chunk of memory, including marking it as read-only. If it
happens to do so, the assignment "*ptr = 111.125;" will likely crash
the program, triggering a segmentation fault or something similar.
But if it happens not to do anything with it immediately, attempts to
access it may still work.

Ok, so the chunk of memory allocated at 0x000209c0 is off-limits after
the call to free(). Attempts to refer to it may happen to work (as
they did when I ran my sample program), but they could just as easily
blow up.

But what about the contents of ptr itself? ptr isn't stored at
0x000209c0, it just points to it. The pointer object is in the local
stack frame of our main program, We should still be able to do
anything we like with the value of ptr, as long as we don't try to
dereference it, right?

Well, yes and no.

On the machine level, on *most* real-world implementations, that's
true. A pointer value is just a bunch of bits, and even though we no
longer own the memory it points to, we still own the pointer itself,
and we can still do things like compare it for equality to another
pointer value.

But the C language standard deliberately doesn't guarantee that.

What happens when we compare two pointer values? On some (probably
most) systems, we're just executing a machine instruction that does a
bit-by-bit comparison of the two values and tells us whether they're
equal. On others, though, there may be special machine instructions
for operating on address values. The program might load the values
into special-purpose address registers before comparing them, and the
very act of loading values into these registers might check whether
the pointers are valid, and trigger a trap if they aren't.

Here's another sample program:

#include <stdio.h>
#include <stdlib.h>
/*
* Warning: This program invokes undefined behavior.
*/
int main(void)
{
double *ptr;
double *copy;

ptr = malloc(sizeof *ptr);
if (ptr != NULL) {
printf("malloc() succeeded\n");
}

copy = ptr;
if (copy == ptr) printf("After malloc, ptr and copy are equal\n");
else printf("After malloc, ptr and copy are unequal (???)\n");

free(ptr);
if (copy == ptr) printf("After free, ptr and copy are still equal\n");
else printf("After free, ptr and copy are unequal (???)\n");

return 0;
}

and here's the output I got when I ran it:

After malloc, ptr and copy are equal
After free, ptr and copy are still equal

On the system I'm using, referring to the value of the pointer after
calling free() doesn't cause any problems; it works just as you might
expect. On a system with the kind of special handling of address
values that I described above, referring to the value of ptr after
calling free() could cause a trap as the value is loaded into a
special address register. Either system could have a conforming C
implementation; either behavior is consistent with the C language
standard, even though the latter might be surprising to many
programmers.

Before the call to free(), the bit pattern 0x000209c0 represents a
valid pointer value. After the call to free(), that same bit pattern
no longer represents a valid pointer value, and any attempt to
reference that value, even without dereferencing it, causes undefined
behavior.

You can't really learn about this kind of thing by running sample
programs and seeing whether they happen to work. Running any number
of sample programs is likely to give you the false impression that the
language makes guarantees that it really doesn't.
free(g);
g = malloc(sizeof *g);

No. The operand of the sizeof operator is not evaluated (unless the
operand is a C99 variable length array, but that doesn't apply here).
The assignment doesn't refer to the value of g, it simply assigns a
new value.


I still cant understand this :-(


The sizeof operator is a special case. Unless the operand is a
variable length array, the operand of sizeof is not evaluated. (Why?
Because the standard says it's not evaluated. Why does the standard
say so? Because there's no need to evaluate the operand; the compiler
needs to know the type of the operand, not its value, and the result
can be, and is, determined during compilation.) The expression
(sizeof *g) doesn't evaluate *g, so it doesn't cause any of the
problems that you might encounter if you did try to evaluate *g.

[...]
I presume you're referring to the second part of my statement; you
agree that C and C++ are two different languages, don't you?


If there was a standardised code of conduct for use in the comp.lang.c, it
would have definitely describe this as an inappropriate behaviour
(and who am I to judge you,e?)


I don't understand why you have a problem with what I wrote above.
ERT made an absurd statement; I was mildly sarcastic in pointing out
the absurdity.
To the original poster (if you haven't given up by now): your original
question was about the new and delete operators, which are specific to
C++ and do not exist in C.


This is true :-). I clicked on the wrong newsgroup.


Fair enough; mistakes happen.
However Robert was kind enough to convert my code in C and answer my
question in terms of C in which I am also interested in. I was wondering how
is it possible to free( ), dereference the pointer and still access the data
which I had assigned before. His example answered exactly this. Then Keith
told me that I should not refer to or dereference a pointer; it may cause an
undefined behaviour. The bottom line is that may and I have learned a lot -
which is the whole point of newsgroups- even though I posted my question to
the wrong newsgroup. There is no need for people to get upset and be rude.
This is what Robert wants to communicate.


If that were all that Robert wants to communicate, we wouldn't have a
problem with him. But he repeatedly posts things here that have the
effect of disrupting this newsgroup. He often does so in a way that
*looks* like he's being kind and helpful to novices, but while doing
so he often posts subtle misinformation, some of which we're unable to
refute effectively because it's off-topic and outside our area of
expertise. When his misinformation is within the scope of
comp.lang.c, many of us feel obligated to spend the considerable time
necessary to correct his errors -- time that we'd much rather spend
doing something more constructive. Some of us are unwilling to let
his statements stand without response, because we're afraid that some
people will assume he's correct.

If you're so inclined, you might want to take a look through the
archives at groups.google.com. Look for things that ERT has posted,
and look at how we've responded to him. (There's a lot of it.) Some
of the responses are admittedly overreactions, but on the whole I
think we've done as good a job as can be expected in an anarchic forum
like this. If you can suggest a more effective way of dealing with
his behavior, we'd love to hear about it. But you really need to have
some understanding of ERT's history in comp.lang.c to understand why
we respond to him as we do.

And by the way, welcome to comp.lang.c. I hope you find it useful,
and I'm sorry that your most recent foray here has dumped you into the
middle of this brouhaha.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #23

P: n/a
Hello,

I really appreciate the help you have all given me

I also do appreciate that you all try to ensure that no one receives wrong
information in this newsgroup. If we all had the sense of duty many would
have been different.

However, I strongly believe that my statement stands even if we remove the
word Robert:
However ........ was kind enough to convert my code in C and answer my
question in terms of C in which I am also interested in. I was wondering how
is it possible to free( ), dereference the pointer and still access the data
which I had assigned before. With his example tried to answered it (ie
after free( ) the pointer doesnt "own" the particular the memory space).
Then Keith told me that I should not refer to or dereference a pointer; it
may cause an undefined behaviour. The bottom line is that may and I have
learned a lot - which is the whole point of newsgroups- even though I posted
my question to the wrong newsgroup. There is no need for people to get upset
and be rude. This is what ........ wants to communicate.

There is no reason to be rude in newsgroups or even get upset by some posts.
The whole idea is openess, sharing of ideas, providing help (which is what
.......... tried to do), co-operation, companionship......
Thanks again and I II speek to you soon :-)
Nov 14 '05 #24

P: n/a
P.S: I am just trying to have a constructive dialog. I am not trying to give
lessons to anybody (anyways I assume you are much older than me :-p )
Nov 14 '05 #25

P: n/a

In article <40**************@jpl.nasa.gov>, "E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
Chris Torek wrote:
Suppose that free() manipulates the segment table
so that the value in %es now refers to an invalid segment,
Your reasoning is fallacious because no implementation of free()
does not, in fact, manipulate the segment table
as you have hypothesized:


The C implmentations for the AS/400 can invalidate pointers in free(),
and indeed do so. Each C pointer is a descriptor that names an address
space and offset, and free() (after validating the descriptor) marks the
address space as invalid. Subsequent attempts to dereference a pointer
to the freed area cause a "trap" (in OS/400 terms, the job is stopped
and a program-error message is sent to the operator's message log, if
no handler for the message is already in force).

While there may not have been any implementation such as Chris describes
for the iAPX family (and good luck proving that negative), there
certainly are equivalent ones for other architectures.
http://www.don-lindsay-archive.org/s...tml#hypothesis


You fail to understand (or deliberately misrepresent) the fallacy of
hypothesis contrary to fact. (Lindsay does a poor job of explaining
it - indeed, he offers almost no explanation whatsoever. I don't
believe rhetoric is well-served by this sort of treatment. It
encourages sophomores.)

Hypothesis contrary to fact is only a fallacy under restrictive
conditions: the hypothesis must be introduced to support an argument
that applies only to past factual matters. If the argument is itself
hypothetical, and touches on future possibilities, then the hypothesis
remains just that - a hypothesis, which (as it pertains to that which
has not yet occurred) is provisional. Or, as in this case, the
example given may be merely illustrative, and not offered as support
for the central claim at all.

There are only two points which are relevant here: the implementation
is allowed to invalidate a pointer passed to free(), and there are
mechanisms by which some implementations could do so.

--
Michael Wojcik mi************@microfocus.com

See who I'm! -- Jackie Chan and unknown subtitler, _Dragons Forever_
Nov 14 '05 #26

P: n/a
mw*****@newsguy.com (Michael Wojcik) writes:
In article <40**************@jpl.nasa.gov>, "E. Robert Tisdale"
<E.**************@jpl.nasa.gov> writes:
Chris Torek wrote:
Suppose that free() manipulates the segment table
so that the value in %es now refers to an invalid segment,


Your reasoning is fallacious because no implementation of free()
does not, in fact, manipulate the segment table
as you have hypothesized:


The C implmentations for the AS/400 can invalidate pointers in free(),
and indeed do so. Each C pointer is a descriptor that names an address
space and offset, and free() (after validating the descriptor) marks the
address space as invalid. Subsequent attempts to dereference a pointer
to the freed area cause a "trap" (in OS/400 terms, the job is stopped
and a program-error message is sent to the operator's message log, if
no handler for the message is already in force).

[...]

Keep in mind that there are two different senses (in terms of the
effects) in which a pointer can become invalid.

The first is demonstrated by:

int *ptr = malloc(sizeof *ptr);
*ptr = 10;
free(ptr);
if (*ptr == 10) ...

The *ptr in the if statement after the free() dereferences ptr, which
invokes undefined behavior because it refers to memory that we no
longer own. On most real-world systems nothing bad will happen, and
*ptr will probably compare equal to 10, but on the AS/400 (if I
understand your description correctly) it could actually cause a trap.

The second is demonstrated by:

int *ptr = malloc(sizeof *ptr);
*ptr = 10;
free(ptr);
if (ptr == NULL) ...

Here we're not dereferencing ptr, so there's no issue of referring to
memory that we no longer own, but referring to the value of ptr itself
invokes undefined behavior. As I explained upthread, it's even more
unlikely that a real-world system will cause a trap, but the standard
specifically allows it to do so.

Question: does the AS/400's invalidation of pointers passed to free()
cause a trap when the pointer value itself is referenced (as in my
second example), or only when it's dereferenced (as in my first)?

In any case, keep in mind that pointer errors are the root cause of
many of the software bugs that enable viruses, root exploits, and
other security breaches. It's not implausible that, with pressure to
plug these holes and advances in hardware technology, future CPUs will
do much more checking in hardware, with the goal of catching errors as
early as possible. Avoiding undefined behavior that happens to do
what you expect on current systems doesn't just give you brownie
points for following the letter of the language standard; it makes it
more likely that your code will continue to work on the systems that
may be common 5 or 10 years from now.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #27

P: n/a
"jimjim" <Fr*********@blueyonder.co.uk> writes:
[...]
(anyways I assume you are much older than me :-p )


Oh, that makes me feel so much better about the whole thing. 8-)}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #28

P: n/a
Keith Thompson wrote:
"jimjim" <Fr*********@blueyonder.co.uk> writes:
[...]
(anyways I assume you are much older than me :-p )

Oh, that makes me feel so much better about the whole thing. 8-)}

Chuck Falconer recently alluded to having an elder but nobody believes
him. We properly revere our elders, jimjim you and the rest of us,
Chuck. :-)

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #29

P: n/a
[I have ERT killfiled so I only saw this in the form of the second
level quotes.]
In article <40**************@jpl.nasa.gov>, "E. Robert Tisdale"
<E.**************@jpl.nasa.gov> ...
accuses me of "hypothesis contrary to fact", which would only be
the case if I claimed some 80x86-based C systems actually *did* it,
rather than "make it possible".

In article <news:c5*********@news4.newsguy.com>
Michael Wojcik <mw*****@newsguy.com> wrote:The C implmentations for the AS/400 can invalidate pointers in free(),
and indeed do so. Each C pointer is a descriptor that names an address
space and offset, and free() (after validating the descriptor) marks the
address space as invalid. Subsequent attempts to dereference a pointer
to the freed area cause a "trap" (in OS/400 terms, the job is stopped
and a program-error message is sent to the operator's message log, if
no handler for the message is already in force).
As described, this is a somewhat weaker form of trapping than that
offered by the iAPX architecture. In this case, consider the code
fragment:

TYPE *p, *q, *r;
...
p = malloc(N * sizeof *p);
q = p;
use(p);
free(p);
r = q; /* allowed to trap */

would not in fact trap on the "r = q" assignment.

Trapping a reference to "*p" or "*q" or "*r" is, of course, also
possible, *does* happen on the AS/400, and *can* be made to happen
on a wide range of current systems using "malloc substitutes"
somewhat like Electric Fence. (I even did my own in-kernel one
for 4.xBSD many years ago, to catch what turned out to be the
use of a "struct proc *" pointer after the process had exited.)

It is, however, not excessively difficult to make the "r = q"
assignment trap on iAPX systems, via the hardware tests that occur
upon loading a segment register.
While there may not have been any implementation such as Chris describes
for the iAPX family (and good luck proving that negative) ...


I suspect none exist. The trick to making it work requires:

a) forcing *all* pointer-value loads to pass a segment number
through one of the segment registers; and

b) cooperation from the operating system (if there *is* an OS)
so that malloc() and free() can manipulate the CPU's
segment table.

Part (a) requires that the compiler emit instructions whose sole
purpose is to catch bugs. These instructions otherwise slow down
correct code. It appears to me that it is commercially impossible
to sell this as a feature: "Our compiler produces 20% slower runtime
code that catches your errors!" :-)

Part (b) is not difficult if you have control over the OS code,
but it then encourages the use of the task-switch instruction[%]
to handle process scheduling inside the OS, and OS-writers have
been avoiding this instruction for decades because it is -- guess
what? -- slow. :-)

[% TSS allows changing the I/O permission maps, segment selector
tables, and various other "CPU state" variables all in one fell
swoop, as it were -- but it costs about as much time as it takes
to change all those state variables. If one forces all processes
to live with a single set of segments and I/O maps, one can switch
between them faster by *not* changing those.

The VAX had similar issues, though 4.1BSD did use the "svpctx"
and "ldpctx" instructions there.]
--
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.
Nov 14 '05 #30

P: n/a

In article <ln************@nuthaus.mib.org>, Keith Thompson <ks***@mib.org> writes:
mw*****@newsguy.com (Michael Wojcik) writes:

The C implmentations for the AS/400 can invalidate pointers in free(),
and indeed do so. Each C pointer is a descriptor that names an address
space and offset, and free() (after validating the descriptor) marks the
address space as invalid. Subsequent attempts to dereference a pointer
to the freed area cause a "trap"...


Question: does the AS/400's invalidation of pointers passed to free()
cause a trap when the pointer value itself is referenced (as in my
second example), or only when it's dereferenced (as in my first)?


To be honest, I don't remember, and I suspect it may depend on
circumstances. AIUI, use of an invalid pointer (whether it involves
dereferencing or simple referencing) is detected and rejected when
the OS/400 MI instruction "matptr" (materialize pointer) is executed.
(MI is the pseudo-assembly language that C and other customer-usable
languages compile to on the '400.)

The compiler generates a matptr for pointer dereferences, but I'm not
sure that it always does so for references.

Note that this also applies to Chris' post regarding pointer aliases.
In the case of:

p = malloc(size);
if (p)
{
q = p;
free(p);
r = q;
}

the '400 should trap that r=q if it does a matptr on q, since the
area named by q is no longer valid. But I don't know whether the
compiler will generate a matptr in this case.

I'll have to write some test programs and see. My AS/400 (which
lives in another state) appears to be down at the moment. (It's
configured to require operator intervention to reboot after a
power failure that outlasts the UPS, unfortunately. Must dig out
the docs and find out how to change that...)

--
Michael Wojcik mi************@microfocus.com

Proverbs for Paranoids, 1: You may never get to touch the Master,
but you can tickle his creatures. -- Thomas Pynchon
Nov 14 '05 #31

This discussion thread is closed

Replies have been disabled for this discussion.