...malloc ...from Rome :-)

  • Follow


Hi all..i'm here another time..for a simple question:

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

int main(void)
{
  /*
  ** I know that someone else use different malloc
  ** instruction
  */

  int *pInt=(int*)malloc(1*sizeof(pInt));

  if(pInt)
  {
    printf("Memory allocated SUCCESS [%p]\n",pInt);
    free(pInt);
  }

  printf("Release memory previously allocated [%p]\n",pInt);

  /*
  ** Why i can see the same address once that i've released?
  */
  
  return 0;
}

Thanks all and have a nice day(???)...

0
Reply claudio.rossetti (23) 10/18/2004 8:44:55 AM

"lasek" <claudio.rossetti@acrm.it> writes:

> Hi all..i'm here another time..for a simple question:
> 
> #include <stdlib.h>
> #include <stdio.h>
> 
> int main(void)
> {
>   /*
>   ** I know that someone else use different malloc
>   ** instruction
>   */
> 
>   int *pInt=(int*)malloc(1*sizeof(pInt));
> 
>   if(pInt)
>   {
>     printf("Memory allocated SUCCESS [%p]\n",pInt);
>     free(pInt);
>   }
> 
>   printf("Release memory previously allocated [%p]\n",pInt);
> 
>   /*
>   ** Why i can see the same address once that i've released?
>   */

The addres will not be removed by free(), only the memory pInt points to
will be freed after the call. It can even happen, that you can access
the memory which was already freed, but this depends on the operatin
system.

Kind regrads,
Nicolas

-- 
|     Nicolas Pavlidis       |       Elvis Presly:    |\ |__      |
|   Student of SE  & KM      |      "Into the goto"   | \|__|     |
|  pavnic@sbox.tugraz.at     |       ICQ #320057056      |        |
|-------------------University of Technology, Graz----------------|
0
Reply pavnic (53) 10/18/2004 8:48:48 AM


In article 
<97608e1aa6b1c5167ada9c19ec3da205@localhost.talkaboutprogramming.com>,
 "lasek" <claudio.rossetti@acrm.it> wrote:

> Hi all..i'm here another time..for a simple question:
> 
> #include <stdlib.h>
> #include <stdio.h>
> 
> int main(void)
> {
>   /*
>   ** I know that someone else use different malloc
>   ** instruction
>   */
> 
>   int *pInt=(int*)malloc(1*sizeof(pInt));

This is bogus -- the (int*) cast is unneeded, and the sizeof() 
expression is wrong.  It should be:

        int *pInt = malloc(1 * sizeof (*pInt));


>   if(pInt)
>   {
>     printf("Memory allocated SUCCESS [%p]\n",pInt);
>     free(pInt);
>   }
> 
>   printf("Release memory previously allocated [%p]\n",pInt);

This provokes undefined behavior -- you may not reference the value of
pInt in any way after it has been passed to free().

Cheers,
- jonathan
0
Reply jwadams (47) 10/18/2004 9:03:33 AM

James Stevenson <james@stev.org> spoke thus:

> if you define int *p;
> it is perforectly ok to access p but not ok to access *p
> after the free is performed.

That is, strictly speaking, incorrect.  See

http://www.eskimo.com/~scs/C-faq/q7.21.html

-- 
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.
0
Reply ataru (1609) 10/18/2004 2:03:09 PM

> This is bogus -- the (int*) cast is unneeded, and the sizeof() 
> expression is wrong.  It should be:
> 
>         int *pInt = malloc(1 * sizeof (*pInt));
> 
> 
> >   if(pInt)
> >   {
> >     printf("Memory allocated SUCCESS [%p]\n",pInt);
> >     free(pInt);
> >   }
> > 
> >   printf("Release memory previously allocated [%p]\n",pInt);
> 
> This provokes undefined behavior -- you may not reference the value of
> pInt in any way after it has been passed to free().

Actually its not.

if you define int *p;
it is perforectly ok to access p but not ok to access *p
after the free is performed.

Also what you seem to impliy is that the value of p
will change once passed to the function free. This is also
not true. Only the memory address that p points to may / may not be 
changed. The actually value of p will remain constant.

	James

-- 
--------------------------
Mobile: +44 07779080838
http://www.stev.org
  3:00pm  up 1 day, 23:42,  5 users,  load average: 0.03, 0.01, 0.00

0
Reply james7839 (12) 10/18/2004 2:11:52 PM

James Stevenson wrote:
> Also what you seem to impliy is that the value of p
> will change once passed to the function free. This is also
> not true. Only the memory address that p points to may / may not be 
> changed. The actually value of p will remain constant.
> 

1) The value of a pointer variable after a call to free is
    indeterminate.
2) Evaluating a variable with a indeterminate value is undefined.

This might seem strange, but the standard is quite clear about
both points above. Can't dig out the quotes just now, but unless
someone else posts them I'll do it later today or tomorrow.

There was a big discussion about this some time ago, maybe google
will have some details.

-- 
Thomas.
0
Reply thomas.stegen (92) 10/18/2004 3:03:11 PM

In article <news:Pine.LNX.4.44.0410181504470.6614-100000@beast.stev.org>
James Stevenson  <james@stev.org> wrote:
>if you define int *p;
>it is perforectly ok to access p but not ok to access *p
>after the free is performed.

The Standard says otherwise.

>Also what you seem to impliy is that the value of p
>will change once passed to the function free. This is also
>not true. Only the memory address that p points to may / may not be 
>changed. The actually value of p will remain constant.

Well, sort of.

The *bit pattern* stored in p will not be changed -- but the *value*
of p might change.

Here is a News Rerun.

From: Chris Torek <nospam@torek.net>
Newsgroups: comp.lang.c
Subject: Re: Malloc/Free - freeing memory allocated by malloc
Date: 23 Sep 2004 01:01:48 GMT
Message-ID: <cit79s11bvd@news2.newsguy.com>
References: <c48d0aae.0409200403.1274d1cb@posting.google.com> <c48d0aae.0409210021.2712d1c1@posting.google.com> <2ranbrF16sh77U1@uni-berlin.de> <cirjao$nn4$1@newshost.mot.com>

>Jens.Toerring@physik.fu-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$1@newshost.mot.com>
Jason Curl <j.curl@motorola.com> 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 (0x12345678) 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 (40�39.22'N, 111�50.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.
0
Reply nospam252 (1722) 10/18/2004 3:43:51 PM

James Stevenson <james@stev.org> writes:
>> This is bogus -- the (int*) cast is unneeded, and the sizeof() 
>> expression is wrong.  It should be:
>> 
>>         int *pInt = malloc(1 * sizeof (*pInt));
>> 
>> 
>> >   if(pInt)
>> >   {
>> >     printf("Memory allocated SUCCESS [%p]\n",pInt);
>> >     free(pInt);
>> >   }
>> > 
>> >   printf("Release memory previously allocated [%p]\n",pInt);
>> 
>> This provokes undefined behavior -- you may not reference the value of
>> pInt in any way after it has been passed to free().
>
> Actually its not.

Actually it is.

> if you define int *p;
> it is perforectly ok to access p but not ok to access *p
> after the free is performed.

No, accessing the value of p after free(p) invokes undefined behavior.

> Also what you seem to impliy is that the value of p
> will change once passed to the function free. This is also
> not true. Only the memory address that p points to may / may not be 
> changed. The actually value of p will remain constant.

The value doesn't necessarily change (in fact I would argue that the
value, or at least its representation, *can't* change), but the value
becomes indeterminate.  On most real-world systems, the resulting
undefined behavior is harmless (the worst kind), but it's
theoretically possible that, for example, an attempt to load the value
into an address register will cause a trap.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21467) 10/18/2004 3:46:52 PM

post...in effect before post this question, it should be better to read
others post..

The post from Chris Torek is very exaustive...

But now i've another doubt:

if i have an expression like this:

struct agenda
{
  char acNome[20];
  struct agenda *next;
};

typedef struct agenda lista_agenda;

lista_agenda *start=NULL;

start=(lista_agenda *)malloc(sizeof(lista_agenda));

/*
** void *malloc(size_t size);
*/
...i need to cast the result from malloc and i don't need to put the
operator '*' inside the sizeof [sizeof(lista_agenda*)]...because i need a
pointer variable to point to a "lista_agenda type".Because if i put the
'*'..with gdb i see a crash when try to strncpy the first members:
"Program received signal SIGSEGV, Segmentation fault.
0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

Is correct ?.

Best regards from Rome.


0
Reply claudio.rossetti (23) 10/18/2004 4:30:22 PM

"James Stevenson" <james@stev.org> wrote in message
news:Pine.LNX.4.44.0410181504470.6614-100000@beast.stev.org...

> > >     free(pInt);
> > >   }
> > >
> > >   printf("Release memory previously allocated [%p]\n",pInt);
> >
> > This provokes undefined behavior -- you may not reference the value of
> > pInt in any way after it has been passed to free().
>
> Actually its not.
>
> if you define int *p;
> it is perforectly ok to access p but not ok to access *p
> after the free is performed.

I used to believe that too -- until I came to clc and
the kind folks here straightened me out. :-)

> Also what you seem to impliy is that the value of p
> will change once passed to the function free. This is also
> not true.

No, in itself that's not necessarily true.  What *is* true
is that the standard specifically states that the result
of evaluating its value is undefined behavior.

>Only the memory address that p points to may / may not be
> changed. The actually value of p will remain constant.

It might, it might not.  But that doesn't matter.

-Mike


0
Reply mkwahler (3821) 10/18/2004 6:40:31 PM

"lasek" <claudio.rossetti@acrm.it> wrote in message
news:7c9024f6e70fed91151e542cbcc2a283@localhost.talkaboutprogramming.com...
> post...in effect before post this question, it should be better to read
> others post..
>
> The post from Chris Torek is very exaustive...

Yes, and sometimes I find reading his stuff to
be exhausting :-), but always worthwhile.

> But now i've another doubt:
>
> if i have an expression like this:
>
> struct agenda
> {
>   char acNome[20];
>   struct agenda *next;
> };
>
> typedef struct agenda lista_agenda;
>
> lista_agenda *start=NULL;
>
> start=(lista_agenda *)malloc(sizeof(lista_agenda));

Stop doing that (casting return value of 'malloc()').
It only can serve to hide a serious error (omitting
'malloc()'s declaration).

#include <stdlib.h>  /* make sure this is at the beginning of your file */
/* etc */
start = malloc(sizeof *start);

>
> /*
> ** void *malloc(size_t size);
> */
> ..i need to cast the result from malloc

No, you do *not*.

>and i don't need to put the
> operator '*' inside the sizeof [sizeof(lista_agenda*)]

The expression 'sizeof(lista_agenda*)' will give the
number of bytes occupied by a pointer (specifically the
size of type 'lista_agenda *').  Not the size of 'struct
agenda'.

>...because i need a
> pointer variable to point to a "lista_agenda type".

'malloc()' returns a pointer to the allocated memory.
Assign it (directly) to 'start'.  Then it does indeed
point to an (uninitialized) object of type 'struct agenda'.
No cast is needed.  A pointer to void can be converted to
any other pointer type  (and back again if desired).  The
language standard specifically states this.

>Because if i put the
> '*'..with gdb i see a crash when try to strncpy the first members:

"I put the '*'", is not specific enough to describe
exactly what you're doing.

> "Program received signal SIGSEGV, Segmentation fault.
> 0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

Show us the *exact* code that produces this behavior.

>
> Is correct ?.

No.

>
> Best regards from Rome.

Um, it seems today I should not "do as the Romans do."  :-)

-Mike


0
Reply mkwahler (3821) 10/18/2004 6:53:42 PM

On Mon, 18 Oct 2004 12:30:22 -0400, in comp.lang.c , "lasek"
<claudio.rossetti@acrm.it> wrote:

>But now i've another doubt:
>
>start=(lista_agenda *)malloc(sizeof(lista_agenda));
>
>..i need to cast the result from malloc 

No you don't,. A C compiler is obliged to ensure that the memory returned
by malloc automatically matches the type you assign it to.

>and i don't need to put the
>operator '*' inside the sizeof [sizeof(lista_agenda*)]...because i need a
>pointer variable to point to a "lista_agenda type".

Yes. To avoid this confusion, use the idiom:

start = malloc(sizeof *start);

>Because if i put the
>'*'..with gdb i see a crash when try to strncpy the first members:
>"Program received signal SIGSEGV, Segmentation fault.
>0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

You have a bug somewhere else in your code. For example, you're corrupting
the memory in your struct, or you're trying to free it twice. 

>Is correct ?.

No
-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/18/2004 7:27:36 PM

On Mon, 18 Oct 2004, Christopher Benson-Manica wrote:

> James Stevenson <james@stev.org> spoke thus:
> 
> > if you define int *p;
> > it is perforectly ok to access p but not ok to access *p
> > after the free is performed.
> 
> That is, strictly speaking, incorrect.  See
> 
> http://www.eskimo.com/~scs/C-faq/q7.21.html

erm thats for the resource it just backs up my statement.

Quote:

Why isn't a pointer null after calling free? 
How unsafe is it to use (assign, compare) a pointer value after it's been 
freed? 

The contents of p are still valid where the contents of where p point are 
no unpredictable. Hence p is still completly valid.

as in

func() {
	int *p = malloc(sizeof(*p));
	if (!p)
		bomb();
	free(p);
	p = (int *) 0;
}

Is perfrectly valid to write.
however *p = 0; after the free would be of course dangerour and 
unpredicatable.

The local variable p as a point is not changed by free in any way.

	James

-- 
--------------------------
Mobile: +44 07779080838
http://www.stev.org
  8:50pm  up 2 days,  5:32,  4 users,  load average: 0.00, 0.00, 0.00

0
Reply james7839 (12) 10/18/2004 7:54:31 PM

> > if you define int *p;
> > it is perforectly ok to access p but not ok to access *p
> > after the free is performed.
> 
> I used to believe that too -- until I came to clc and
> the kind folks here straightened me out. :-)
> 
> > Also what you seem to impliy is that the value of p
> > will change once passed to the function free. This is also
> > not true.
> 
> No, in itself that's not necessarily true.  What *is* true
> is that the standard specifically states that the result
> of evaluating its value is undefined behavior.
> 
> >Only the memory address that p points to may / may not be
> > changed. The actually value of p will remain constant.
> 
> It might, it might not.  But that doesn't matter.

then this would dictate that free is not a function but a macro
otherwise it has no way of changing the value of p directly.

Last time i check free was a function not a macro or did i mis something.
but of course the contents of p probably are not usefull in any case after 
free has been called :)

	James

-- 
--------------------------
Mobile: +44 07779080838
http://www.stev.org
  9:10pm  up 2 days,  5:52,  5 users,  load average: 0.00, 0.02, 0.00


0
Reply james7839 (12) 10/18/2004 8:18:46 PM

"James Stevenson" <james@stev.org> wrote in message
news:Pine.LNX.4.44.0410182115590.6956-100000@beast.stev.org...
>
> > > if you define int *p;
> > > it is perforectly ok to access p but not ok to access *p
> > > after the free is performed.
> >
> > I used to believe that too -- until I came to clc and
> > the kind folks here straightened me out. :-)
> >
> > > Also what you seem to impliy is that the value of p
> > > will change once passed to the function free. This is also
> > > not true.
> >
> > No, in itself that's not necessarily true.  What *is* true
> > is that the standard specifically states that the result
> > of evaluating its value is undefined behavior.
> >
> > >Only the memory address that p points to may / may not be
> > > changed. The actually value of p will remain constant.
> >
> > It might, it might not.  But that doesn't matter.
>
> then this would dictate that free is not a function but a macro

No.

> otherwise it has no way of changing the value of p directly.

Note that the language standard does not prohibit 'magic' (or anything
else) as an implementation method.  Behavior is what is specified
(or specifically left 'undefined' or 'implementation-defined', etc.)
The 'pass-by-value' semantics of C don't necessarily apply in this
case.  This is why the explicit verbiage of the standard.
("or if the space has been deallocated by a call to free or realloc,
the behavior is undefined.")

> Last time i check free was a function not a macro or did i mis something.

It's a function (but whose internal operational details are
left to the implementation).

> but of course the contents of p probably are not usefull

Not just not useful, not defined.  A particular implementation
might choose to define and/or use this "value" in some way, but
such usage falls outside the domain of the standard language/library.

>in any case after
> free has been called :)

Right. Thus the practice by many of assigning NULL to the pointer
immediately after 'free()' (some wrap 'free' in a macro for this
purpose), so they can inspect its value before subsequent use.
Treat a pointer passed to 'free()' as you would an uninitialized
object, i.e. "no peeking" (but of course you're free :-) to assign
it a new value).


-Mike


0
Reply mkwahler (3821) 10/18/2004 8:24:49 PM

James Stevenson <james@stev.org> spoke thus:

> erm thats for the resource it just backs up my statement.

A careful reading reveals the opposite:

"A pointer value which has been freed is, strictly speaking, invalid,
and any use of it, even if is not dereferenced can theoretically
lead to trouble..."

The key portion is "even if it is not dereferenced"; IOW, the value of
the pointer may not be used in any way once it has been passed to
free().  Specifically, it may not be passed to the printf as an 
argument for the %p conversion specifier, as in the OP's code:

if(pInt)
{
  printf("Memory allocated SUCCESS [%p]\n",pInt);
  free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

While the FAQ notes that on reasonable implementations it is likely 
to be altogether harmless, the code as written exhibits undefined 
behavior (as other more learned posters have also pointed out).
Therefore your original statement:

"[I]t is perforectly ok to access p but not ok to access *p after the
free is performed."

is incorrect.  Of course, the code you supplied

> func() {
> 	int *p = malloc(sizeof(*p));
> 	if (!p)
> 		bomb();
> 	free(p);
> 	p = (int *) 0;
> }

is correct; the value of the freed pointer is not used.  However, it
does contain an unnecessary cast of 0 to (int *); 0 in a pointer
context is guaranteed to yield the same value as the macro NULL.

-- 
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.
0
Reply ataru (1609) 10/18/2004 8:37:39 PM

"James Stevenson" <james@stev.org> wrote in message
news:Pine.LNX.4.44.0410182051200.6956-100000@beast.stev.org...
>
> On Mon, 18 Oct 2004, Christopher Benson-Manica wrote:
>
> > James Stevenson <james@stev.org> spoke thus:
> >
> > > if you define int *p;
> > > it is perforectly ok to access p but not ok to access *p
> > > after the free is performed.
> >
> > That is, strictly speaking, incorrect.  See
> >
> > http://www.eskimo.com/~scs/C-faq/q7.21.html
>
> erm thats for the resource it just backs up my statement.

Huh?

> Quote:
>
> Why isn't a pointer null after calling free?
> How unsafe is it to use (assign, compare) a pointer value after it's been
> freed?
>
> The contents of p are still valid where the contents of where p point are
> no unpredictable. Hence p is still completly valid.
>
> as in
>
> func() {
> int *p = malloc(sizeof(*p));
> if (!p)
> bomb();
> free(p);
> p = (int *) 0;
> }
>
> Is perfrectly valid to write.
> however *p = 0; after the free would be of course dangerour and
> unpredicatable.
>
> The local variable p as a point is not changed by free in any way.

That is not what appears at that URL.  This is:


============ begin quote ================================

Question 7.21

Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been
freed?

----------------------------------------------------------------------------
----

When you call free, the memory pointed to by the passed pointer is freed,
but the value of the pointer in the caller remains unchanged, because C's
pass-by-value semantics mean that called functions never permanently change
the values of their arguments. (See also question 4.8.)

A pointer value which has been freed is, strictly speaking, invalid, and any
use of it, even if is not dereferenced can theoretically lead to trouble,
though as a quality of implementation issue, most implementations will
probably not go out of their way to generate exceptions for innocuous uses
of invalid pointers.

References: ANSI Sec. 4.10.3
ISO Sec. 7.10.3
Rationale Sec. 3.2.2.3


This page by Steve Summit // Copyright 1995

============ end quote ================================


This does seem to indicate that a (valid, evaluable) expression
can switch from 'valid' to 'invalid' without it's 'value' having
changed. The standard appears to allow this, which imo it has every
right to do, being the definition of how things behave (there
are many stated exceptions to certain behaviors scattered throughout).
However the second paragraph does clearly state the actual facts.

Perhaps you're looking at some other 'FAQ' or an older,
incorrect version of this one and failed to refresh your
browser cache?


-Mike


0
Reply mkwahler (3821) 10/18/2004 8:41:10 PM

In article <Pine.LNX.4.44.0410182051200.6956-100000@beast.stev.org>,
 James Stevenson <james@stev.org> wrote:

> On Mon, 18 Oct 2004, Christopher Benson-Manica wrote:
> 
> > James Stevenson <james@stev.org> spoke thus:
> > 
> > > if you define int *p;
> > > it is perforectly ok to access p but not ok to access *p
> > > after the free is performed.
> > 
> > That is, strictly speaking, incorrect.  See
> > 
> > http://www.eskimo.com/~scs/C-faq/q7.21.html
> 
> erm thats for the resource it just backs up my statement.
> 
> Quote:
> 
> Why isn't a pointer null after calling free? 
> How unsafe is it to use (assign, compare) a pointer value after it's been 
> freed? 
> 
> The contents of p are still valid where the contents of where p point are 
> no unpredictable. Hence p is still completly valid.

Read that second question again -- it is talking about the *value* of 
the pointer, not what the pointer points at.

> as in
> 
> func() {
>         int *p = malloc(sizeof(*p));
>         if (!p)
>                 bomb();
>         free(p);
>         p = (int *) 0;
> }
> 
> Is perfrectly valid to write.

Yes.  No one has said that otherwise (you're overwriting the value of p,
not using it)

> however *p = 0; after the free would be of course dangerour and 
> unpredicatable.

Yes.  The standard also says that:

        char *q;

        free(p);
        q = p;          /* undefined */
        if (p != NULL)  /* undefined */
               /* ... */ 

leads to undefined behavior.  

> The local variable p as a point is not changed by free in any way.

Indeed it isn't.  That doesn't mean it is safe to use its value. 

Cheers,
- jonathan
0
Reply jwadams (47) 10/18/2004 8:48:59 PM

James Stevenson <james@stev.org> writes:
> On Mon, 18 Oct 2004, Christopher Benson-Manica wrote:
>> James Stevenson <james@stev.org> spoke thus:
>> 
>> > if you define int *p;
>> > it is perforectly ok to access p but not ok to access *p
>> > after the free is performed.
>> 
>> That is, strictly speaking, incorrect.  See
>> 
>> http://www.eskimo.com/~scs/C-faq/q7.21.html
>
> erm thats for the resource it just backs up my statement.

Um, no it doesn't.

> Quote:
>
> Why isn't a pointer null after calling free? 
> How unsafe is it to use (assign, compare) a pointer value after it's been 
> freed? 
>
> The contents of p are still valid where the contents of where p point are 
> no unpredictable. Hence p is still completly valid.

Nope.  FAQ 7.21 says:

    A pointer value which has been freed is, strictly speaking,
    invalid, and any use of it, even if is not dereferenced can
    theoretically lead to trouble, though as a quality of
    implementation issue, most implementations will probably not go
    out of their way to generate exceptions for innocuous uses of
    invalid pointer

> as in
>
> func() {
> 	int *p = malloc(sizeof(*p));
> 	if (!p)
> 		bomb();
> 	free(p);
> 	p = (int *) 0;
> }
>
> Is perfrectly valid to write.
> however *p = 0; after the free would be of course dangerour and 
> unpredicatable.

Yes, the above is perfectly valid, since it doesn't access the value
of p after the call to free().

It's important to distinguish between an object (p in this case) and
the current value of an object.  After free(p), p is still a pointer
object, and you can take its address or assign a value to it.  You can
do anything that doesn't examine the value stored in p.  But if you do
examine its value, you invoke undefined behavior.  So the following is
ok:

    int *p = malloc(sizeof *p);
    free(p); /* valid whether malloc succeeded or not */
    p = NULL;

but this is not:

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

> The local variable p as a point is not changed by free in any way.

The bits making up the value of p don't change; what changes is
whether the value is indeterminate.

With a few system-specific assumptions:

    int *p = malloc(sizeof *p);
    /*
     * Assume that malloc succeeded, and that the value stored in p
     * is represented as 0x12345678; this is the address of the
     * allocated memory.  (int*)0x12345678 is now a valid pointer
     * value.
     */
    free(p);
    /*
     * This informs the system that we're finished with the memory
     * allocated by malloc().  It doesn't change the representation of
     * the value of p, but that unchanged value has become
     * indeterminate.  (int*)0x12345678 is now an indeterminate
     * pointer value.  An attempt to dereference it obviously invokes
     * undefined behavior.  Less obviously, but just as true, an
     * attempt to examine the value, such as (p == NULL), also invokes
     * undefined behavior.  You can still retrieve the representation
     * by aliasing p with an array of unsigned char, but there's
     * little reason for doing so.
     */

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21467) 10/18/2004 8:58:57 PM

Mark McIntyre <markmcintyre@spamcop.net> writes:
> On Mon, 18 Oct 2004 12:30:22 -0400, in comp.lang.c , "lasek"
> <claudio.rossetti@acrm.it> wrote:
>
>>But now i've another doubt:
>>
>>start=(lista_agenda *)malloc(sizeof(lista_agenda));
>>
>>..i need to cast the result from malloc 
>
> No you don't,. A C compiler is obliged to ensure that the memory returned
> by malloc automatically matches the type you assign it to.

It's true that you don't need the cast, but your explanation is a bit
off.

malloc doesn't return the allocated memory, it returns a pointer to
it.  The allocated memory is guaranteed to be suitably aligned for any
type of object, but that's not why the cast is unnecessary.  The cast
is unnecessary because malloc returns a result of type void*, and a
value of type void* can be implicitly converted to any
pointer-to-object type.  (The suitable alignment is what makes the
result useful.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21467) 10/18/2004 9:03:14 PM

On Mon, 18 Oct 2004 21:03:14 GMT, in comp.lang.c , Keith Thompson
<kst-u@mib.org> wrote:

>It's true that you don't need the cast, but your explanation is a bit
>off.

I prefer "oversimplified".... :-) 
But I agree with your correction. 

By the way sorry if my posts start appearing multiple times - my news
provider is having some sort of hairy fit and seems to be rejecting but at
the same time accepting some postings. Gah.



-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/18/2004 9:42:32 PM

On Mon, 18 Oct 2004 21:18:46 +0100, in comp.lang.c , James Stevenson
<james@stev.org> wrote:

>someone whose attribution James snipped said, talking of free. 

>> It might, it might not.  But that doesn't matter.
>
>then this would dictate that free is not a function but a macro
>otherwise it has no way of changing the value of p directly.

free() is part of the implementation. It can do all sorts of things that're
not allowed by users of the implementation. 
-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/18/2004 9:46:03 PM

James Stevenson wrote: *** And again rudely removed attributes ***
> 
.... snip ...
>>
>> No, in itself that's not necessarily true.  What *is* true
>> is that the standard specifically states that the result
>> of evaluating its value is undefined behavior.
>>
>>> Only the memory address that p points to may / may not be
>>> changed. The actually value of p will remain constant.
>>
>> It might, it might not.  But that doesn't matter.
> 
> then this would dictate that free is not a function but a macro
> otherwise it has no way of changing the value of p directly.

>From the FAQ:
    A pointer value which has been freed is, strictly speaking,
    invalid, and *any* use of it, even if it is not dereferenced,
    can theoretically lead to trouble, though as a quality of
    implementation issue, most implementations will probably not go
    out of their way to generate exceptions for innocuous uses of
    invalid pointers.

    References: ISO Sec. 7.10.3; Rationale Sec. 3.2.2.3.

That pointer p might signal, on dereference:  Wake up the small boy
and send him donw to Joes house to pick up that piece of paper in
the front parlor.  Bring it back and read it to me.

Printing the pointer value (via %p) might mean wake up the boy and
have him scream his name.

free may well signal: Send the small boy home for a nights sleep,
and destroy that paper at some future time.

After that the boy is no longer available to scream his name.

-- 
 Some informative links:
   news:news.announce.newusers
   http://www.geocities.com/nnqweb/
   http://www.catb.org/~esr/faqs/smart-questions.html
   http://www.caliburn.nl/topposting.html
   http://www.netmeister.org/news/learn2quote.html

0
Reply cbfalconer (19183) 10/18/2004 10:02:30 PM

"Mike Wahler" <mkwahler@mkwahler.net> writes:
[...]
> This page by Steve Summit // Copyright 1995
[...]
>
> Perhaps you're looking at some other 'FAQ' or an older,
> incorrect version of this one and failed to refresh your
> browser cache?

I think we can safely assume that he's refreshed his browser cache
some time in the last 9 years.  (If he hasn't, that's actually pretty
impressive in its own way.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21467) 10/18/2004 10:03:44 PM

James Stevenson <james@stev.org> wrote:
> > 
> > This provokes undefined behavior -- you may not reference the value of
> > pInt in any way after it has been passed to free().
> 
> Actually its not.
> 
> if you define int *p;
> it is perforectly ok to access p 

p (as well as *p) becomes indeterminate after free() is called.
Accessing of indeterminate values is undefined behaviour (3.18#1).

> but not ok to access *p after the free is performed.
> 
> Also what you seem to impliy is that the value of p
> will change once passed to the function free. This is also
> not true. 

Actually it is true. After a call to free(), the value passed
in becomes indeterminate. (The representation doesn't change,
obviously, but the value of that representation has changed).
N869 6.2.4 (especially, the second sentence):

[#6]  If  an  object  is  referred  to  when  storage is not
   reserved for it, the behavior is undefined.  The value of  a
   pointer  that  referred  to  an  object  whose storage is no
   longer reserved is indeterminate.  During the time that  its
   storage is reserved, an object has a constant address.
0
Reply oldwolf (2278) 10/18/2004 10:21:27 PM

On Mon, 18 Oct 2004 12:30:22 -0400, in comp.lang.c , "lasek"
<claudio.rossetti@acrm.it> wrote:

>But now i've another doubt:
>
>start=(lista_agenda *)malloc(sizeof(lista_agenda));
>
>..i need to cast the result from malloc 

No you don't,. A C compiler is obliged to ensure that the memory returned
by malloc automatically matches the type you assign it to.

>and i don't need to put the
>operator '*' inside the sizeof [sizeof(lista_agenda*)]...because i need a
>pointer variable to point to a "lista_agenda type".

Yes. To avoid this confusion, use the idiom:

start = malloc(sizeof *start);

>Because if i put the
>'*'..with gdb i see a crash when try to strncpy the first members:
>"Program received signal SIGSEGV, Segmentation fault.
>0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

You have a bug somewhere else in your code. For example, you're corrupting
the memory in your struct, or you're trying to free it twice. 

>Is correct ?.

No
-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/18/2004 10:37:32 PM

James Stevenson wrote:

> 
>> > if you define int *p;
>> > it is perforectly ok to access p but not ok to access *p
>> > after the free is performed.
>> 
>> I used to believe that too -- until I came to clc and
>> the kind folks here straightened me out. :-)
>> 
>> > Also what you seem to impliy is that the value of p
>> > will change once passed to the function free. This is also
>> > not true.
>> 
>> No, in itself that's not necessarily true.  What *is* true
>> is that the standard specifically states that the result
>> of evaluating its value is undefined behavior.
>> 
>> >Only the memory address that p points to may / may not be
>> > changed. The actually value of p will remain constant.
>> 
>> It might, it might not.  But that doesn't matter.
> 
> then this would dictate that free is not a function but a macro
> otherwise it has no way of changing the value of p directly.

The value doesn't change. It simply ceases to be defined. What this means is
simply:
void *p = malloc(1);
p; /* Defined behavior in the ISO C standard */
free(p);
p; /* Anything can happen here. */

> Last time i check free was a function not a macro or did i mis something.
> but of course the contents of p probably are not usefull in any case after
> free has been called :)
> 
> James
> 

0
Reply bdonlan2 (53) 10/18/2004 11:57:25 PM

On 18 Oct 2004 15:21:27 -0700, oldwolf@inspire.net.nz (Old Wolf) wrote
in comp.lang.c:

> James Stevenson <james@stev.org> wrote:
> > > 
> > > This provokes undefined behavior -- you may not reference the value of
> > > pInt in any way after it has been passed to free().
> > 
> > Actually its not.
> > 
> > if you define int *p;
> > it is perforectly ok to access p 
> 
> p (as well as *p) becomes indeterminate after free() is called.
> Accessing of indeterminate values is undefined behaviour (3.18#1).

Perhaps you should spend the money on a copy of the real standard.
N869 is obsolete, and the wording you refer to that specifically
states does not exist in the actual standard.  It was removed after
N869.  Nowhere in the standard does it state that using the value of
an indeterminate object causes undefined behavior.

> > but not ok to access *p after the free is performed.
> > 
> > Also what you seem to impliy is that the value of p
> > will change once passed to the function free. This is also
> > not true. 
> 
> Actually it is true. After a call to free(), the value passed
> in becomes indeterminate. (The representation doesn't change,
> obviously, but the value of that representation has changed).
> N869 6.2.4 (especially, the second sentence):
> 
> [#6]  If  an  object  is  referred  to  when  storage is not
>    reserved for it, the behavior is undefined.  The value of  a
>    pointer  that  referred  to  an  object  whose storage is no
>    longer reserved is indeterminate.  During the time that  its
>    storage is reserved, an object has a constant address.

This is more wording that is not in the actual standard.  The last
sentence of paragraph 2 of 6.2.4 does say "The value of a pointer
becomes indeterminate when the object it points to reaches the end of
its lifetime."

But as I said, nowhere in the actual standard does it state that
accessing an indeterminate value is undefined.

-- 
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
0
Reply jackklein (3932) 10/19/2004 3:06:49 AM

Hiiiiii....always from Rome....and today the weather is a little
dirt...(like Alice in Chains....);however, i've a little script that
allocate memory for first time when i created the 'agenda':

naturally start is global an it was declared:

struct agenda
{
  char acNome[20];
  struct agenda *next;
};

typedef struct agenda lista_agenda;

lista_agenda *start=NULL;

void crea_agenda()
{
  start=(lista_agenda *)malloc(sizeof(lista_agenda));

  if(start!=NULL)
  {
    memset((char *)start->acNome,'\0',sizeof(start->acNome));

    scanf("%s",start->acNome);

    start->next=NULL;
  }
}

When i insert a new value, i need to add a new node, so:

void inserisci()
{
  char newNome[20]={0};
  unsigned int iLen;

  lista_agenda *newrecord;
  lista_agenda *locate;
  lista_agenda *localizza(lista_agenda *ptStruct);

  printf("\nNew name:");

  scanf("%s",newName);

  iLen=sizeof(newName);

  /*
  ** this function return a pointer to the last node in
  ** the list.
  */

  locate=localizza(start);

  if(newNome)
  {
    /*
    ** Now i know that cast the return value from malloc
    ** is not correct but this is my original code.
    */

    newrecord=(lista_agenda *)malloc(sizeof(lista_agenda));

    if(newrecord)
    {
      strncpy(newrecord->acNome,newNome,iLen);

      locate->next=newrecord;

      newrecord->next=NULL;
    }
    else
      printf("Impossibile allocare lo spazio richiesto.\n");
  }
}

The error i receive when i try to add a new node it depends from the
malloc function i use, in particular:

newrecord=(lista_agenda *)malloc(sizeof(lista_agenda));
This line above is ok(from my gdb).
Also because, (i think) i must allocate for the entire size of my struct
and not the size of a pointer to the struct.
(i'm not sure but if i execute a sizeof of a pointer a can see always 4
byte;maybe u'm wrong).

The line below give me an strange error from (gdb):
newrecord=(lista_agenda *)malloc(sizeof(lista_agenda*));

"
Program received signal SIGSEGV, Segmentation fault.
0x4207aecc in chunk_free () from /lib/i686/libc.so.6
(gdb) where
#0  0x4207aecc in chunk_free () from /lib/i686/libc.so.6
#1  0x4207a60a in chunk_alloc () from /lib/i686/libc.so.6
#2  0x4207a058 in malloc () from /lib/i686/libc.so.6
#3  0x08048790 in ?? ()
#4  0x08048599 in ?? ()
#5  0x42017499 in __libc_start_main () from /lib/i686/libc.so.6
".

Thanks all for your patience...


0
Reply claudio.rossetti (23) 10/19/2004 8:30:38 AM

lasek wrote:

> The line below give me an strange error from (gdb):
> newrecord=(lista_agenda *)malloc(sizeof(lista_agenda*));

This is the way, that they like to write something like that,
on this newsgroup:

#include <stdlib.h>
newrecord = malloc(sizeof *newrecord);

Don't forget #include <stdlib.h>

-- 
pete
0
Reply pfiland (6613) 10/19/2004 11:38:02 AM

James Stevenson <james@stev.org> wrote:

[ Please stop snipping all attributions - leave those which refer to
  text that's still in the post. ]

> > >Only the memory address that p points to may / may not be
> > > changed. The actually value of p will remain constant.
> > 
> > It might, it might not.  But that doesn't matter.
> 
> then this would dictate that free is not a function but a macro
> otherwise it has no way of changing the value of p directly.

It needn't change p directly. Even disregarding implementation magic,
what about a function which doesn't change the bit pattern of p, but
does release the segment p refers to from the allocated segment tables?
In that case, p has suddenly changed from "my memory" to "someone else's
memory - there's nothing for me there". Even referring to p's value
could now cause a segmentation violation.

Richard
0
Reply rlb (4118) 10/19/2004 2:16:36 PM

Jack Klein <jackklein@spamcop.net> writes:
[...]
> This is more wording that is not in the actual standard.  The last
> sentence of paragraph 2 of 6.2.4 does say "The value of a pointer
> becomes indeterminate when the object it points to reaches the end of
> its lifetime."
>
> But as I said, nowhere in the actual standard does it state that
> accessing an indeterminate value is undefined.

But in the case of a freed pointer, I think we can infer that
accessing its value causes undefined behavior.

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

C99 3.17.2:
    indeterminate value
    either an unspecified value or a trap representation

C99 3.17.3:
    unspecified value    
    valid value of the relevant type where this International Standard
    imposes no requirements on which value is chosen in any instance
    NOTE An unspecified value cannot be a trap representation.

C99 6.2.6.1p5:
    Certain object representations need not represent a value of the
    object type. If the stored value of an object has such a
    representation and is read by an lvalue expression that does not
    have character type, the behavior is undefined. If such a
    representation is produced by a side effect that modifies all or
    any part of the object by an lvalue expression that does not have
    character type, the behavior is undefined.  Such a representation
    is called a _trap representation_.

So after free(p), p has an indeterminate value, which may be either an
unspecified value (which is a valid value of the type) or a trap
representation.  If it's a trap representation, accessing the value
invokes undefined behavior; if it's merely unspecified, it doesn't.
An implementation is certainly allowed to make it a trap
representation, and isn't required to document whether it does or not.

I'm not particularly happy with the standard's use of the term
"indeterminate value" here rather than "trap representation".  In
effect, accessing p may or may not invoke undefined behavior; this is
indistinguishible from saying that accessing p *does* invoke undefined
behavior.  The standard could simply have said that the value of the
pointer becomes a trap representation with, as far as I can tell, no
effect on any implementation.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21467) 10/19/2004 6:17:57 PM

Jack Klein <jackklein@spamcop.net> wrote:
Old Wolf wrote:
> 
> > 
> > p (as well as *p) becomes indeterminate after free() is called.
> > Accessing of indeterminate values is undefined behaviour (3.18#1).
> 
> Perhaps you should spend the money on a copy of the real standard.

Probably true

> N869 is obsolete, and the wording you refer to that specifically
> states does not exist in the actual standard.  It was removed after
> N869.  Nowhere in the standard does it state that using the value of
> an indeterminate object causes undefined behavior.

What does it say instead (for example how does it deal with the
possibility of an indeterminate value being a trap representation), 
and what does C89 have to say?
0
Reply oldwolf (2278) 10/19/2004 8:44:05 PM

On Mon, 18 Oct 2004 12:30:22 -0400, in comp.lang.c , "lasek"
<claudio.rossetti@acrm.it> wrote:

>But now i've another doubt:
>
>start=(lista_agenda *)malloc(sizeof(lista_agenda));
>
>..i need to cast the result from malloc 

No you don't,. A C compiler is obliged to ensure that the memory returned
by malloc automatically matches the type you assign it to.

>and i don't need to put the
>operator '*' inside the sizeof [sizeof(lista_agenda*)]...because i need a
>pointer variable to point to a "lista_agenda type".

Yes. To avoid this confusion, use the idiom:

start = malloc(sizeof *start);

>Because if i put the
>'*'..with gdb i see a crash when try to strncpy the first members:
>"Program received signal SIGSEGV, Segmentation fault.
>0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

You have a bug somewhere else in your code. For example, you're corrupting
the memory in your struct, or you're trying to free it twice. 

>Is correct ?.

No
-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/19/2004 11:22:01 PM

On Mon, 18 Oct 2004 21:03:14 GMT, in comp.lang.c , Keith Thompson
<kst-u@mib.org> wrote:

>It's true that you don't need the cast, but your explanation is a bit
>off.

I prefer "oversimplified".... :-) 
But I agree with your correction. 

By the way sorry if my posts start appearing multiple times - my news
provider is having some sort of hairy fit and seems to be rejecting but at
the same time accepting some postings. Gah.



-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/19/2004 11:22:28 PM

On Tue, 19 Oct 2004, Richard Bos wrote:

> James Stevenson <james@stev.org> wrote:
> 
> [ Please stop snipping all attributions - leave those which refer to
>   text that's still in the post. ]
> 
> > > >Only the memory address that p points to may / may not be
> > > > changed. The actually value of p will remain constant.
> > > 
> > > It might, it might not.  But that doesn't matter.
> > 
> > then this would dictate that free is not a function but a macro
> > otherwise it has no way of changing the value of p directly.
> 
> It needn't change p directly. Even disregarding implementation magic,
> what about a function which doesn't change the bit pattern of p, but
> does release the segment p refers to from the allocated segment tables?
> In that case, p has suddenly changed from "my memory" to "someone else's
> memory - there's nothing for me there". Even referring to p's value
> could now cause a segmentation violation.

yeah i can follow that now its kind of like
the old dos problem with far pointers where you end up working on a 16bit
and being able to address more than 64kb of data baecause of the segment 
selector. Which used to be called far pointers but c compilers used to 
"hide" this functionallity.

I was not aware any processors would have trapped on accessing the value 
of an pointer would have cause this to happen.

I assume now the same can also happen with something like this.

int *p;
printf("%p\n");

on the same sorts of system.


	James



0
Reply james7839 (12) 10/19/2004 11:43:43 PM

"Mark McIntyre" <markmcintyre@spamcop.net> wrote in message
news:id8bn0hfq0lb656iv8s7k3n9g2s7pabjtm@4ax.com...
> On Mon, 18 Oct 2004 21:03:14 GMT, in comp.lang.c , Keith Thompson
> <kst-u@mib.org> wrote:
>
> >It's true that you don't need the cast, but your explanation is a bit
> >off.
>
> I prefer "oversimplified".... :-)
> But I agree with your correction.
>
> By the way sorry if my posts start appearing multiple times - my news
> provider is having some sort of hairy fit and seems to be rejecting but at
> the same time accepting some postings. Gah.

I suggest you get a 'backup' provider.  My provider's servers
sometime get 'sick' too, in which case I fall back on
'individual.news.NET'.  It takes them a few days to
activate an account after registration, but now it's
there when I need it.  And there are many others out there.

-Mike


0
Reply mkwahler (3821) 10/20/2004 12:18:24 AM

>yeah i can follow that now its kind of like
>the old dos problem with far pointers where you end up working on a 16bit
>and being able to address more than 64kb of data baecause of the segment 
>selector. Which used to be called far pointers but c compilers used to 
>"hide" this functionallity.
>
>I was not aware any processors would have trapped on accessing the value 
>of an pointer would have cause this to happen.

The Intel *86 architecture (in 16-bit or 32-bit protected mode) is
an excellent example of this.  Loading a (so-called "far") pointer
containing a no-longer-valid segment into, say, ES:SI or ES:ESI
will cause a trap.

>I assume now the same can also happen with something like this.
>
>int *p;
>printf("%p\n");
>
>on the same sorts of system.

Yes, but you didn't need the declaration of p to get undefined
behavior.  Just leaving off the argument to printf() matching %p
is enough.

						Gordon L. Burditt
0
Reply gordonb.n8qq3 (1) 10/20/2004 2:19:24 AM

gordonb.n8qq3@burditt.org (Gordon Burditt) writes:
>>yeah i can follow that now its kind of like
>>the old dos problem with far pointers where you end up working on a 16bit
>>and being able to address more than 64kb of data baecause of the segment 
>>selector. Which used to be called far pointers but c compilers used to 
>>"hide" this functionallity.
>>
>>I was not aware any processors would have trapped on accessing the value 
>>of an pointer would have cause this to happen.
>
> The Intel *86 architecture (in 16-bit or 32-bit protected mode) is
> an excellent example of this.  Loading a (so-called "far") pointer
> containing a no-longer-valid segment into, say, ES:SI or ES:ESI
> will cause a trap.

Does loading a null pointer into ES:SI or ES:ESI cause a trap?

>>I assume now the same can also happen with something like this.
>>
>>int *p;
>>printf("%p\n");
>>
>>on the same sorts of system.
>
> Yes, but you didn't need the declaration of p to get undefined
> behavior.  Just leaving off the argument to printf() matching %p
> is enough.

Yes, but that illustrates a different point.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21467) 10/20/2004 4:28:23 AM

>gordonb.n8qq3@burditt.org (Gordon Burditt) writes:
>> The Intel *86 architecture (in 16-bit or 32-bit protected mode) is
>> an excellent example of this.  Loading a (so-called "far") pointer
>> containing a no-longer-valid segment into, say, ES:SI or ES:ESI
>> will cause a trap.

In article <lnwtxmko7u.fsf@nuthaus.mib.org>,
Keith Thompson  <kst-u@mib.org> wrote:
>Does loading a null pointer into ES:SI or ES:ESI cause a trap?

It could be arranged to do so, by making NULL's segment invalid.

If a compiler/system did set this up, so that in:

    char *p, *q;
    p = NULL;
    q = p;

the assigment "q = p" trapped by loading p's NULL-value segment
into a segment register, that compiler/system would fail to conform.
The easiest way to fix this is to make sure that the "null segment"
(whatever segment number the compiler-writer chooses) is always
valid, if for some reason it is important to allow "q = p" to load
p's segment into a segment register.

In other words, simply loading a bad pointer into causes a trap, but it
should be OK to "load NULL", as long as you do not indirect through it:

    p = NULL;
    use(p); /* OK */
    use2(*p); /* ERROR */

so a compiler must not trap on the call to use(), in case it
longjmp()s away.  If it traps on the call to use2() (assuming this
call is actually attempted), that is fine.  Since the hardware
traps on a load of the segment register with an invalid segment,
either NULL's segment has to be invalid, or the call to use()
has to not load the segment register (or both).
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.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.
0
Reply nospam252 (1722) 10/20/2004 5:13:49 AM

Typo alert (low blood sugar? :-) ... was posting just post-gym):

In article <news:cl4s6d02sek@news2.newsguy.com> I wrote:
>... Since the hardware
>traps on a load of the segment register with an invalid segment,
>either NULL's segment has to be invalid, or the call to use()
>has to not load the segment register (or both).

Of course, that should read "either NULL's segment has to be VALID"
(not "invalid").
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.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.
0
Reply nospam252 (1722) 10/20/2004 5:25:40 AM

>>>yeah i can follow that now its kind of like
>>>the old dos problem with far pointers where you end up working on a 16bit
>>>and being able to address more than 64kb of data baecause of the segment 
>>>selector. Which used to be called far pointers but c compilers used to 
>>>"hide" this functionallity.
>>>
>>>I was not aware any processors would have trapped on accessing the value 
>>>of an pointer would have cause this to happen.
>>
>> The Intel *86 architecture (in 16-bit or 32-bit protected mode) is
>> an excellent example of this.  Loading a (so-called "far") pointer
>> containing a no-longer-valid segment into, say, ES:SI or ES:ESI
>> will cause a trap.
>
>Does loading a null pointer into ES:SI or ES:ESI cause a trap?

That depends on what bit pattern you use for a null pointer.  The
short answer is NO for an all-bits-zero null pointer.

I think some of the logic in handling selectors on the x86 architecture
was designed for C.

The all-bits-zero selector (actually, the two low-order bits of 16
are a don't care in this situation) generates a trap if you load
it into CS or SS.  It doesn't cause a trap if you load it into DS,
ES, FS or GS.  You *CANNOT* map that selector to anything.  You
also can't dereference the pointer without a trap.

You can't load an all-bits-zero selector into CS since loading
CS:EIP is a branch instruction, and it's impossible to avoid
dereferencing it on the next instruction.  The processor is rather
picky about keeping a valid stack pointer and it's difficult to
avoid dereferences into the stack segment if SS is NULL.  I suppose
you could come up with a useful code sequence that loads SS with
NULL and manages not to dereference it, but the processor doesn't
allow it.

					Gordon L. Burditt
0
Reply gordonb.g1644 (1) 10/20/2004 5:33:26 AM

>>> The Intel *86 architecture (in 16-bit or 32-bit protected mode) is
>>> an excellent example of this.  Loading a (so-called "far") pointer
>>> containing a no-longer-valid segment into, say, ES:SI or ES:ESI
>>> will cause a trap.

>The easiest way to fix this is to make sure that the "null segment"
>(whatever segment number the compiler-writer chooses) is always
>valid, if for some reason it is important to allow "q = p" to load
>p's segment into a segment register.
>
>In other words, simply loading a bad pointer into causes a trap, but it
>should be OK to "load NULL", as long as you do not indirect through it:
>
>    p = NULL;
>    use(p); /* OK */
>    use2(*p); /* ERROR */
>
>so a compiler must not trap on the call to use(), in case it
>longjmp()s away.  If it traps on the call to use2() (assuming this
>call is actually attempted), that is fine.  Since the hardware
>traps on a load of the segment register with an invalid segment,
>either NULL's segment has to be invalid, or the call to use()
                                 valid
>has to not load the segment register (or both).

BUT, there's an odd halfway-in-between case for the all-bits-zero
selector (Intel x86 architecture):  it's always a valid segment (so
you can load the pointer into a segment register without a trap),
but you can't dereference it.  Just what you'd want for a null
pointer.  And that particular selector ALWAYS acts like that:  you
can't change it.

						Gordon L. Burditt
0
Reply gordonb.2jpqs (1) 10/20/2004 6:39:54 AM

Gordon Burditt wrote:
> 
.... snip ...
> 
> BUT, there's an odd halfway-in-between case for the all-bits-zero
> selector (Intel x86 architecture):  it's always a valid segment (so
> you can load the pointer into a segment register without a trap),
> but you can't dereference it.  Just what you'd want for a null
> pointer.  And that particular selector ALWAYS acts like that:  you
> can't change it.

Oh, you can dereference it, but you probably shouldn't.  If you do
you are messing with the zero-divide interrupt vector, IIRC.

-- 
 "I support the Red Sox and any team that beats the Yankees"
 "Any baby snookums can be a Yankee fan, it takes real moral
  fiber to be a Red Sox fan"
 "I listened to Toronto come back from 3:0 in '42, I plan to 
  watch Boston come back from 3:0 in 04"


0
Reply cbfalconer (19183) 10/20/2004 8:54:03 AM

On 20 Oct 2004, Gordon Burditt wrote:

> >yeah i can follow that now its kind of like
> >the old dos problem with far pointers where you end up working on a 16bit
> >and being able to address more than 64kb of data baecause of the segment 
> >selector. Which used to be called far pointers but c compilers used to 
> >"hide" this functionallity.
> >
> >I was not aware any processors would have trapped on accessing the value 
> >of an pointer would have cause this to happen.
> 
> The Intel *86 architecture (in 16-bit or 32-bit protected mode) is
> an excellent example of this.  Loading a (so-called "far") pointer
> containing a no-longer-valid segment into, say, ES:SI or ES:ESI
> will cause a trap.
> 
> >I assume now the same can also happen with something like this.
> >
> >int *p;
> >printf("%p\n");
> >
> >on the same sorts of system.
> 
> Yes, but you didn't need the declaration of p to get undefined
> behavior.  Just leaving off the argument to printf() matching %p
> is enough.

Yeah please note the time on the posting 

Date: Wed, 20 Oct 2004 00:43:43 +0100
From: James Stevenson <james@stev.org>



-- 
--------------------------
Mobile: +44 07779080838
http://www.stev.org
 12:30pm  up 19:28,  5 users,  load average: 3.89, 3.88, 3.77

0
Reply james7839 (12) 10/20/2004 11:39:24 AM

In article <cl4s6d02sek@news2.newsguy.com>,
Chris Torek  <nospam@torek.net> wrote:

>In other words, simply loading a bad pointer into causes a trap, but it
>should be OK to "load NULL", as long as you do not indirect through it:
>
>    p = NULL;
>    use(p); /* OK */
>    use2(*p); /* ERROR */
>
>so a compiler must not trap on the call to use(), in case it
>longjmp()s away.

Isn't it enough for use() to involve user-visible side effects like
input or output?

Or would that lead us to a long and twisty thread arguing about what
constitutes a strictly conforming use of user-visible side effects,
rather than simply invalidating a trap on the call to use()?


dave

-- 
Dave Vandervies                               dj3vande@csclub.uwaterloo.ca
But they're not strings. Not being strings doesn't stop them being useful.
After all, ints aren't strings, yet they are very useful indeed!
                                       --Richard Heathfield in comp.lang.c
0
Reply dj3vande (656) 10/20/2004 6:50:43 PM

On Wed, 20 Oct 2004 00:18:24 GMT, in comp.lang.c , "Mike Wahler"
<mkwahler@mkwahler.net> wrote:

>"Mark McIntyre" <markmcintyre@spamcop.net> wrote in message
>>
>> By the way sorry if my posts start appearing multiple times - my news
>> provider is having some sort of hairy fit and seems to be rejecting but at
>> the same time accepting some postings. Gah.
>
>I suggest you get a 'backup' provider. 

I have one. Problem was that my normal provider was *silently*
rejecting-but-accepting posts, and didn't advise my newsclient till I tried
to end the session.... 


-- 
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
0
Reply markmcintyre (4547) 10/20/2004 7:29:09 PM

>In article <cl4s6d02sek@news2.newsguy.com>,
>Chris Torek  <nospam@torek.net> wrote:
>>    p = NULL;
>>    use(p); /* OK */
>>    use2(*p); /* ERROR */
>>... a compiler must not trap on the call to use(), in case it
>>longjmp()s away.

In article <news:cl6c23$j87$1@rumours.uwaterloo.ca>
Dave Vandervies <dj3vande@csclub.uwaterloo.ca> wrote:
>Isn't it enough for use() to involve user-visible side effects like
>input or output?
>
>Or would that lead us to a long and twisty thread arguing about what
>constitutes a strictly conforming use of user-visible side effects,
>rather than simply invalidating a trap on the call to use()?

It gets particularly complicated if we allow "undefined behavior"
to violate the laws of physics. :-)

Seriously, I figured longjmp() was a simple example of "control
may never reach use2()".  Other possibilities include exit()ing,
and doing irreversible user-visible side effects... but consider
how tricky "irreversible" might be.  Suppose use(p) does:

    write(1, "use() called\n", 13); /* POSIX */

so that "use() called" appears on stdout.  This is certainly
user-visible -- or is it?  What if it goes into a terminal-simulator
window that, before the pixels are even drawn on the screen, is
completely destroyed when use2(*p) causes the system to crash and
reboot?

Or, to rephrase the old saw about a tree in a forest:  If a windows
box bluescreens before you can see a particular result, did it even
compute the result?
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.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.
0
Reply nospam252 (1722) 10/20/2004 7:32:47 PM

>> BUT, there's an odd halfway-in-between case for the all-bits-zero
>> selector (Intel x86 architecture):  it's always a valid segment (so
>> you can load the pointer into a segment register without a trap),
>> but you can't dereference it.  Just what you'd want for a null
>> pointer.  And that particular selector ALWAYS acts like that:  you
>> can't change it.
>
>Oh, you can dereference it, but you probably shouldn't.  If you do
>you are messing with the zero-divide interrupt vector, IIRC.

No, you AREN'T messing with the zero-divide interrupt vector.  The
global table doesn't have an entry 0 (even though where it would
logically go may overlap that vector).  If you try to dereference a
NULL pointer (all-zero-bit selector), the processor won't look at
that entry, and even if you screw up the zero-divide vector to be
a valid table entry with associated memory, the dereference won't
work.

The all-bits zero selector (low-order two bits actually are don't-cares)
is a special case designed into the chip.

						Gordon L. Burditt
0
Reply gordonb.do3hr (1) 10/20/2004 7:36:20 PM

On 20 Oct 2004 19:36:20 GMT, gordonb.do3hr@burditt.org (Gordon Burditt)
wrote:

>>> BUT, there's an odd halfway-in-between case for the all-bits-zero
>>> selector (Intel x86 architecture):  it's always a valid segment (so
>>> you can load the pointer into a segment register without a trap),
>>> but you can't dereference it.  Just what you'd want for a null
>>> pointer.  And that particular selector ALWAYS acts like that:  you
>>> can't change it.
>>
>>Oh, you can dereference it, but you probably shouldn't.  If you do
>>you are messing with the zero-divide interrupt vector, IIRC.
>
>No, you AREN'T messing with the zero-divide interrupt vector.  The
>global table doesn't have an entry 0 (even though where it would
>logically go may overlap that vector).

Take a look at the following output from "debug.exe":
>-d 0000:0000
:0000:0000  68 10 A7 00 BB 13 53 05-16 00 9A 03 B1 13 53 05   h.....S.......S.
:0000:0010  8B 01 70 00 B9 06 10 02-40 07 10 02 FF 03 10 02   ..p.....@.......
:0000:0020  46 07 10 02 0A 04 10 02-3A 00 9A 03 54 00 9A 03   F.......:...T...
:0000:0030  6E 00 9A 03 88 00 9A 03-A2 00 9A 03 FF 03 10 02   n...............
:0000:0040  A9 08 10 02 A4 09 10 02-AA 09 10 02 5D 04 10 02   ............]...
:0000:0050  B0 09 10 02 0D 02 DF 02-C4 09 10 02 8B 05 10 02   ................
:0000:0060  0E 0C 10 02 14 0C 10 02-1F 0C 10 02 AD 06 10 02   ................
:0000:0070  AD 06 10 02 A4 F0 00 F0-37 05 10 02 42 42 00 C0   ........7...BB..
:-g=00a7:1068
:
:Divide overflow

If it looks like a duck, walks like a duck and quacks like a duck...

> If you try to dereference a
>NULL pointer (all-zero-bit selector), the processor won't look at
>that entry, and even if you screw up the zero-divide vector to be
>a valid table entry with associated memory, the dereference won't
>work.

If the processor didn't allow access to the null pointer, than I wouldn't
have been able to retrieve the address of the interrupt vector, let alone
know call it.  If I wanted to, I could set the Zero-divide interrupt vector
to whatever I wanted, even something that could potentially reset the
computer.

The only reason the processor would prevent the address from being touched
is if it is running in protected mode.  In this case, the interrupt table
is moved elsewhere in memory, and applications running under the
protected-mode kernel are given their own private address space.  However,
it can still be possible to crash the system if the kernel allows it (e.g.
running debug under the default memory setting under Windows 95.)


0
Reply bk039 (205) 10/21/2004 4:10:17 AM

Gordon Burditt wrote:
> 
>>> BUT, there's an odd halfway-in-between case for the all-bits-zero
>>> selector (Intel x86 architecture):  it's always a valid segment (so
>>> you can load the pointer into a segment register without a trap),
>>> but you can't dereference it.  Just what you'd want for a null
>>> pointer.  And that particular selector ALWAYS acts like that:  you
>>> can't change it.
>>
>> Oh, you can dereference it, but you probably shouldn't.  If you do
>> you are messing with the zero-divide interrupt vector, IIRC.
> 
> No, you AREN'T messing with the zero-divide interrupt vector.  The
> global table doesn't have an entry 0 (even though where it would
> logically go may overlap that vector).  If you try to dereference a
> NULL pointer (all-zero-bit selector), the processor won't look at
> that entry, and even if you screw up the zero-divide vector to be
> a valid table entry with associated memory, the dereference won't
> work.
> 
> The all-bits zero selector (low-order two bits actually are
> don't-cares) is a special case designed into the chip.

Then how does the zero-divide vector get set in the first place?

-- 
 "I support the Red Sox and any team that beats the Yankees"
 "Any baby snookums can be a Yankee fan, it takes real moral
  fiber to be a Red Sox fan"
 "I listened to Toronto come back from 3:0 in '42, I plan to 
  watch Boston come back from 3:0 in 04"


0
Reply cbfalconer (19183) 10/21/2004 5:38:46 AM

(This is getting off-topic, and probably should move to some
x86-specific newsgroup...)

>Gordon Burditt wrote:
>> No, you AREN'T messing with the zero-divide interrupt vector.  The
>> global table doesn't have an entry 0 (even though where it would
>> logically go may overlap that vector). ...  even if you screw up
>> the zero-divide vector to be a valid table entry with associated
>> memory, the dereference won't work.
>> 
>> The all-bits zero selector (low-order two bits actually are
>> don't-cares) is a special case designed into the chip.

In article <news:4176E31E.CC43A40@yahoo.com>
CBFalconer  <cbfalconer@worldnet.att.net> wrote:
>Then how does the zero-divide vector get set in the first place?

I am not an expert on the x86 architecture, and would have to haul
out my Pentium book to go into all the details, but this is mixing
up several different concepts.

The x86 has three "descriptor tables" involved here, called the GDT,
LDT, and IDT.  These stand for "Global", "Local", and "Interrupt"
Descriptor Table.

Exceptions, including zero-divide, indirect through the IDT.  Segments
loaded into data registers indirect through the GDT or LDT.

A "logical" (user-supplied) memory address -- this may be a virtual
memory address, depending on processor mode -- as specified by a
segment register plus another 16 or 32 bits of "address" register
(depending on mode) is handled by combining the DT-lookup-result
(from the segment) with the rest of the address.  If this is a
virtual address, it is then run through a virtual-to-physical
translation.  The final physical address, if valid, determines what
memory is read or written.

It is possible to have the GDT and IDT overlap, in which case IDT#0
is the zero-divide vector while IDT#1 is also GDT#1.  Here GDT#0 is
unused (as Gordon Burditt pointed out -- this was not something I was
aware of), but you can access it by going through some nonzero GDT
entry.  That is, just set DS to (say) 5000, making sure that the
GDT has at least 5001 entries starting with the unused #0, with
GDT[5000] mapping that same memory, and you are all set.

(I think it makes more sense to just set the IDT somewhere else,
myself, but it can be done this way.)
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.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.
0
Reply nospam252 (1722) 10/21/2004 6:11:13 AM

>>>> BUT, there's an odd halfway-in-between case for the all-bits-zero
>>>> selector (Intel x86 architecture):  it's always a valid segment (so
>>>> you can load the pointer into a segment register without a trap),
>>>> but you can't dereference it.  Just what you'd want for a null
>>>> pointer.  And that particular selector ALWAYS acts like that:  you
>>>> can't change it.
>>>
>>>Oh, you can dereference it, but you probably shouldn't.  If you do
>>>you are messing with the zero-divide interrupt vector, IIRC.
>>
>>No, you AREN'T messing with the zero-divide interrupt vector.  The
>>global table doesn't have an entry 0 (even though where it would
>>logically go may overlap that vector).
>
>Take a look at the following output from "debug.exe":
>>-d 0000:0000
[snip]

My bet is that MS-DOS is not running in protected mode.  "selectors" only
exist in protected mode.  The context of this thread is 16-bit or 32-bit
protected mode, where loading an invalid selector into a segment register
will cause a trap.

>> If you try to dereference a
>>NULL pointer (all-zero-bit selector), the processor won't look at
>>that entry, and even if you screw up the zero-divide vector to be
>>a valid table entry with associated memory, the dereference won't
>>work.
>
>If the processor didn't allow access to the null pointer, than I wouldn't
>have been able to retrieve the address of the interrupt vector, let alone
>know call it.  If I wanted to, I could set the Zero-divide interrupt vector
>to whatever I wanted, even something that could potentially reset the
>computer.

Selectors only exist in protected mode, and that's not what MS-DOS is running.

>The only reason the processor would prevent the address from being touched
>is if it is running in protected mode.  In this case, the interrupt table
>is moved elsewhere in memory, and applications running under the
>protected-mode kernel are given their own private address space.  However,
>it can still be possible to crash the system if the kernel allows it (e.g.
>running debug under the default memory setting under Windows 95.)

						Gordon L. Burditt
0
Reply gordonb.inge4 (1) 10/21/2004 4:01:52 PM

> >Take a look at the following output from "debug.exe":
> >>-d 0000:0000
> [snip]
> 
> My bet is that MS-DOS is not running in protected mode.  "selectors" only
> exist in protected mode.  The context of this thread is 16-bit or 32-bit
> protected mode, where loading an invalid selector into a segment register
> will cause a trap.

Ok explain how memory is access in MS-DOS at an address greater than
0xFFFF since it is running in 16-Bit real mode 0xFFFF is the highest 
memory address you can possibly have. But yet it was possible to use
the whole < 640Kb (subtract tsr's of course) region using far pointers and 
memory selectors.

 

-- 
--------------------------
Mobile: +44 07779080838
http://www.stev.org
 12:50am  up 1 day, 11:16,  4 users,  load average: 0.00, 0.02, 0.00

0
Reply james7839 (12) 10/21/2004 11:54:30 PM

>> >Take a look at the following output from "debug.exe":
>> >>-d 0000:0000
>> [snip]
>> 
>> My bet is that MS-DOS is not running in protected mode.  "selectors" only
>> exist in protected mode.  The context of this thread is 16-bit or 32-bit
>> protected mode, where loading an invalid selector into a segment register
>> will cause a trap.
>
>Ok explain how memory is access in MS-DOS at an address greater than
>0xFFFF since it is running in 16-Bit real mode 0xFFFF is the highest 
>memory address you can possibly have. 

Incorrect.  You can address 1 megabyte in real mode.  (using "far"
pointers, which in some memory models are the default for C).  Ever
wonder why the addresses for the BIOS and hardware devices start
at 1 megabyte and reach down to 640k?

>But yet it was possible to use
>the whole < 640Kb (subtract tsr's of course) region using far pointers and 
>memory selectors.

NO, you're not using memory selectors.  You're using the segment
register to refer to the base of a segment in terms of multiples
of 16-byte "pages".  Selectors exist only in protected mode.

In real mode, physical address = 16*segment register + offset .
The segment register and offset are each 16 bits in 16-bit real
mode.  Thus, you can address 1 megabyte.  Well, ok, in some cases
1 megabyte plus almost 64k.  But what you put in a segment register
in real mode is *NOT* a selector.

In real mode, 0x0000:0x0080 and 0x0008:0x0000 refer to the same
byte.  In 16-bit protected mode, these addresses may be nowhere
near each other, as each refers to a different potentially 64k-long
segment.

Some extended memory managers use protected mode but run MS-DOS in
virtual 8086 mode, where segment registers act like they are in
real mode, but "windows" in memory (typically in the 640k - 1024k
range) can be remapped to memory above 1 meg ("extended memory").
Others use some kind of hardware remapping not provided by the CPU
("expanded memory").  It is also possible to escape from 16-bit
real mode into 32-bit mode using instruction prefixes on Intel
[3456]86 processors.

In protected mode, there are 2**13 (8192) possible local table
entries and 2**13-1 (8191) possible global table entries (table
entry 0 is not used in the global table).  Without changing the
table, you can address, in 16-bit protected mode, 8192*2**16 = about
0.5 gigabytes local memory, and almost the same in global memory,
using a 32-bit "far" pointer (16-bit selector, 16-bit offset).  In
32-bit protected mode (16-bit selector, 32-bit offset), that's about
32 gigabytes each, local and global, for a 48-bit "far" pointer.
(The processor may not be able to address that much *PHYSICAL*
memory, though).

						Gordon L. Burditt
0
Reply gordonb.u8dr8 (1) 10/22/2004 1:36:06 AM

Gordon Burditt wrote:
> 
> [snip]
> 
> My bet is that MS-DOS is not running in protected mode. 
> "selectors" only exist in protected mode.  The context of this
> thread is 16-bit or 32-bit protected mode, where loading an
> invalid selector into a segment register will cause a trap.

No, this is c.l.c, and the presence or absense of MS-DOS,
selectors, protected mode etc. is not germane.  Dereferencing NULL
is UB.  Anything further is idle back room gossip about what form
that UB is likely to take.

-- 
 "I support the Red Sox and any team that beats the Yankees"
 "Any baby snookums can be a Yankee fan, it takes real moral
  fiber to be a Red Sox fan" - "I listened to Toronto come back
  from 3:0 in '42, I watched Boston come back from 3:0 in '04"


0
Reply cbfalconer (19183) 10/22/2004 7:51:38 AM

55 Replies
36 Views

(page loaded in 0.479 seconds)


Reply: