Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #30037 > unrolled thread
| Started by | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| First post | 2013-01-12 14:52 -0800 |
| Last post | 2013-01-16 10:59 -0800 |
| Articles | 20 on this page of 85 — 9 participants |
Back to article view | Back to comp.lang.c
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-12 14:52 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-13 15:19 -0500
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-14 12:04 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-14 18:52 -0500
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-16 00:01 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-16 05:43 -0500
Re: [union] Pointers to inherited structs are valid ? Geoff <geoff@invalid.invalid> - 2013-01-16 09:01 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-16 18:32 -0500
Re: [union] Pointers to inherited structs are valid ? Geoff <geoff@invalid.invalid> - 2013-01-16 17:32 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-16 20:57 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-17 07:55 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-17 16:47 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-18 08:41 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-18 15:53 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-18 17:38 -0800
Re: [union] Pointers to inherited structs are valid ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-19 02:31 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-18 23:15 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-19 20:03 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-20 02:19 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-20 07:57 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-20 15:25 -0500
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-20 23:58 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-20 21:30 -0500
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-21 02:53 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 00:05 -0500
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-21 16:31 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 14:07 -0500
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-21 21:05 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 17:13 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-21 16:11 -0800
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 04:59 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-22 01:05 -0500
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-22 14:53 +0000
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 08:38 -0800
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-21 20:53 -0800
Re: [union] Pointers to inherited structs are valid ? Philip Lantz <prl@canterey.us> - 2013-01-22 00:58 -0800
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 08:40 -0800
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 23:32 -0800
Re: [union] Pointers to inherited structs are valid ? Philip Lantz <prl@canterey.us> - 2013-01-23 23:21 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-24 04:53 -0500
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-25 10:49 -0800
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 08:25 -0800
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-22 23:41 -0800
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-21 13:32 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 17:46 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 07:43 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-22 16:07 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 14:15 -0800
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 14:31 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-22 21:32 -0500
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-23 17:17 -0500
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-23 19:49 -0500
Re: [union] Pointers to inherited structs are valid ? Geoff <geoff@invalid.invalid> - 2013-01-23 18:55 -0800
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-24 11:01 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-24 14:11 -0500
Re: [union] Pointers to inherited structs are valid ? Geoff <geoff@invalid.invalid> - 2013-01-22 17:51 -0800
Re: [union] Pointers to inherited structs are valid ? Philip Lantz <prl@canterey.us> - 2013-01-20 16:48 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-20 21:33 -0500
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-21 09:23 -0800
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-20 17:07 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-20 22:20 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-20 22:02 -0800
Re: [union] Pointers to inherited structs are valid ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-21 07:00 +0000
Re: [union] Pointers to inherited structs are valid ? James Kuyper <jameskuyper@verizon.net> - 2013-01-21 08:17 -0500
Re: [union] Pointers to inherited structs are valid ? Dr Nick <nospam-4@temporary-address.org.uk> - 2013-01-21 14:13 +0000
Re: [union] Pointers to inherited structs are valid ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-21 14:12 +0000
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-21 08:20 -0800
Re: [union] Pointers to inherited structs are valid ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-21 20:41 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 12:37 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-21 12:17 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 16:33 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-21 15:50 -0800
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-21 19:45 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-22 00:18 -0500
Re: [union] Pointers to inherited structs are valid ? Keith Thompson <kst-u@mib.org> - 2013-01-22 08:01 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-18 23:02 -0500
Re: [union] Pointers to inherited structs are valid ? Philip Lantz <prl@canterey.us> - 2013-01-19 01:28 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-19 12:08 -0500
Re: [union] Pointers to inherited structs are valid ? Geoff <geoff@invalid.invalid> - 2013-01-21 09:27 -0800
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 12:46 -0500
Re: [union] Pointers to inherited structs are valid ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-21 20:48 +0000
Re: [union] Pointers to inherited structs are valid ? Geoff <geoff@invalid.invalid> - 2013-01-21 18:52 -0800
Re: [union] Pointers to inherited structs are valid ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-22 04:07 +0000
Re: [union] Pointers to inherited structs are valid ? Shao Miller <sha0.miller@gmail.com> - 2013-01-21 23:15 -0500
Re: [union] Pointers to inherited structs are valid ? Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-16 10:59 -0800
Page 3 of 5 — ← Prev page 1 2 [3] 4 5 Next page →
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-25 10:49 -0800 |
| Message-ID | <kfnwqv1rtbg.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30604 |
Philip Lantz <prl@canterey.us> writes: > Tim Rentsch wrote: >> Philip Lantz writes: >> > I think there may be one more kind of pointer value, which is the >> > kind that caused this thread. It is a value that may appear in a >> > pointer object as a result of some prior undefined behavior. This >> > is of course outside the scope of the C standard--which is why it >> > correctly doesn't appear in your list--but it does occur in actual >> > implementations. >> > >> > It behaves much like your type 1, but I'm not sure it's identical; >> > in particular, its behavior can't be described by referring to the >> > standard. Before reading this thread, I would not have ever >> > thought to call it a trap representation, but it is pretty >> > similar. >> >> Let me see if I can help untangle the description you're giving. >> >> [snip] >> >> Of course, it should go without saying that the above assumes there >> has been no previous undefined behavior. > > Of course. So why did you write five paragraphs (reiterating stuff I > already know) when I specifically said there was prior undefined > behavior? My previous posting (ie the response to Ben Bacarisse's post) was, pretty clearly, only about how the Standard identifies different kinds of behaviors, not anything more fine-grained. Your response to that blurs the distinction between the two. I think it's important to clarify which is which. As for your question, well, I don't know what you know and what you don't know, but even if I did, I wasn't writing just for you. What I'm hoping to do is lay a clear foundation so that the less well understood aspects can be discussed effectively. >> A kind of value along the lines >> you describe -- we might call it "semi-defined" -- would be a >> subset of the Type 1 class, not a separate class. > > Wait, what? You think that the kind of value I describe, > *specifically caused by prior undefined behavior*, is a subset > of one of your classes, Yes. The various categories are each definitional, and together they completely partition the space of pointer values. > which specifically assume there has been no prior undefined > behavior? Here there is a mistake in logical inference. When I say "the above assumes there has been no previous undefined behavior", it means only that _some_ of the previous conclusions might not hold if there has been previous undefined behavior, not that they all might not. In any event, the descriptions of the different classes are definitions, not conclusions. To be fair I should add that these details may not have been clear in my earlier writing. >> Whenever there has been any previous undefined behavior, any >> assertion about how subsequent actions will proceed might not >> hold up. There isn't any point in talking about what might be >> true under such circumstances ... > > Then why have you guys been talking about it for days? I haven't. I only followed up to Ben Bacarisse's post because I thought some people might find it helpful. However, to clarify my earlier statement, there isn't any point in talking about what might be true under such circumstances _without some additional information_ that puts some sort of bounds on (some cases of) undefined behavior. The key is to identify which kinds of transgressions now have identifiable semantics, and what the semantics are in such cases. But this isn't easy. > The only reason to talk about it is that when someone is > debugging and observes unexpected behavior (behavior that was > unexpected by the one doing the debugging, of course), it > sometimes helps to consider -- in the context of an actual > implementation -- how undefined behavior can lead to the > observed behavior, as a means of working backward to locate the > actual bug. My contributions to this thread have been a vain > attempt to point the discussion in this direction. In effect what's going on there -- ie, the considering -- is imagining a more well-defined semantics for cases which are UB as far as the Standard is concerned. It's important to know both which cases have more well-defined semantics and what the new semantics are. For example, on many machines, comparing pointers using < always works for well-behaved pointer values, even if they aren't in the same array, and even if one or both is a null pointer. We might imagine a new semantics where < works with all pointer values, and returns the right answer for cases the Standard says are defined, and a "random" answer for the other cases. So as long as the program doesn't depend in a drastic way on the results of such pointer comparisons, they are harmless -- nothing bad will happen if there is a stray comparison here and there (and for which both possible outcomes cause no further problems). But: tread cautiously! A similar example might reason that null pointers have the value zero, and the memory around that location is accessible, so dereferencing a null pointer is harmless if the resulting value is ignored. OOPS! This is exactly the kind of reasoning that led to the famous bug in the Linux kernel, because gcc relied on the unlimited latitude of earlier undefined behavior. So, bottom line... I agree that thinking about what might have happened, undefined-behavior-wise, can be helpful in tracking down a problem. But is also much harder than thinking about just what well behaved programs will do, because of the myriad ways that implementations can (and do!) manifest undefined behavior. And if in spite of that someone wants to consider the consequences of "semi-defined" behavior, they better be doggone sure they know what the heck the implementation is doing (because there is a pretty good chance it isn't doing what they think it's doing).
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-22 08:25 -0800 |
| Message-ID | <ln1udd5gni.fsf@nuthaus.mib.org> |
| In reply to | #30492 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
[...]
> Actually there are four kinds of pointer values (with the
> understanding that "value" here includes some that cannot
> be used definedly):
>
> 1. unusable (any use is undefined behavior)
> 2. null pointers (can be compared for equality/inequality)
> 3. equality, pointer arithmetic, relational (eg <) comparison
> 4. like 3 but also can be dereferenced
>
> Type 3 values are, eg, pointers one past the end of an array, or
> non-null values returned from doing a malloc(0). Type 4 values
> are regular pointers to objects.
[...]
And I believe that type 1 is exactly the set of trap representations,
but I haven't been able to prove it.
The definition of "trap representation" in 3.19.4 is a bit vague:
trap representation
an object representation that need not represent a value of the
object type
I wonder why it doesn't say "does not" rather than "need not".
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-22 23:41 -0800 |
| Message-ID | <kfntxq8qrbh.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30508 |
Keith Thompson <kst-u@mib.org> writes: > Tim Rentsch <txr@alumni.caltech.edu> writes: > [...] >> Actually there are four kinds of pointer values (with the >> understanding that "value" here includes some that cannot >> be used definedly): >> >> 1. unusable (any use is undefined behavior) >> 2. null pointers (can be compared for equality/inequality) >> 3. equality, pointer arithmetic, relational (eg <) comparison >> 4. like 3 but also can be dereferenced >> >> Type 3 values are, eg, pointers one past the end of an array, or >> non-null values returned from doing a malloc(0). Type 4 values >> are regular pointers to objects. > [...] > > And I believe that type 1 is exactly the set of trap representations, > but I haven't been able to prove it. My response to Philip Lantz gives a line of reasoning related to this. > The definition of "trap representation" in 3.19.4 is a bit vague: > > trap representation > > an object representation that need not represent a value of the > object type > > I wonder why it doesn't say "does not" rather than "need not". Because implementations may define (either explicitly or implicitly) what happens for such representations so that they do represent well-behaved values _in some cases_. Saying that a TR need not represent a value of the object type leaves open the possibility that under some circumstances it might be okay. Basically, it lets the implementation eat its cake and have it too.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-21 13:32 -0800 |
| Message-ID | <lnpq0y5iil.fsf@nuthaus.mib.org> |
| In reply to | #30470 |
Shao Miller <sha0.miller@gmail.com> writes:
[...]
> I agree that his post does look that way and that C does allow for
> that. There's a subtle bit here, though: If we're discussing a
> program, once that program invokes undefined behaviour, anything goes.
> However, if I'm not mistaken, with Windows NT, if you have a pointer
> value which does not point to an object, the program will continue to
> operate as per the C semantics until such a time (if ever) as that
> pointer might be used for indirect access.
I (mostly) agree with that.
> So it is imprecise to say that such a value has a trap representation,
> because the behaviour is still well-defined. Otherwise, the last
> sentence of N1570's 6.5.3.2p4 is redundant:
>
> "If an invalid value has been assigned to the pointer, the behavior
> of the unary * operator is undefined.102)"
No. Accessing an object with a trap representation has undefined
behavior. What that means is that the behavior is not defined *by the C
standard*; see N1370 3.4.3, the definion of the phrase "undefined
behavior". Another entity can certainly define behavior for such
accesses.
For example, (void*)0x0000000C is very likely a trap representation
under Windows NT. The behavior of applying unary "*" to that value is
undefined, in the sense that the C standard does not define its
behavior. Windows NT can define the behavior if it likes; that doesn't
cause it to cease being a trap representation.
> But anyway, a pointer value pointing to no object can still be
> "trapped" by Windows during indirection and can still provide useful
> information to a Windows debugger. It just does not precisely match
> C's trap representation, for behavioural differences.
Yes, it does.
[...]
> Take Windows NT's 'IRP' structure. It has a sub-member called
> Tail.Overlay.DriverContext', which is an array of 4 'void *'. This is
> one of _very_few_ places where a driver can associate information with
> an IRP, and is extremely valuable for that reason.
>
> The implementation defines the results of casting an
> appropriately-sized integer value to a 'void *', so such an integer
> can be "passed" via this mechanism. We _certainly_ would not wish to
> believe that this results in undefined behaviour, so we certainly
> would not wish to believe that such a result is a trap representation.
I'm afraid that what you wish is irrelevant. It has undefined behavior.
A program that depends on the behavior of some construct whose behavior
is not defined by the C standard is not portable. There's nothing wrong
with that; sometimes you *need* to write non-portable code, code that
depends on guarantees made by a given environment but not by the
language standard.
Don't forget that "undefined behavior" does not* mean "this will crash".
It means exactly what the C standard says it means in 3.4.3: "behavior,
upon use of a nonportable or erroneous program construct or of erroneous
data, for which this International Standard imposes no requirements".
A given construct causing Microsoft's debugger to consistently display a
"NULL_CLASS_PTR_DEREFERENCE" message is perfectly consistent with that
construct having undefined behavior as defined by the C standard. If
you don't understand that, you don't understand undefined behavior.
>>> B: "Here are Microsoft's documented [non-C] trap values..."
>>
>> If this was Geoff, he correctly called then "trap representation"
>> (rather than values) and he referred to "they" meaning the C committee.
>> He was talking at C trap representations not "[non-C] trap values".
>>
>
> This was in regards to the lower part of his post where he
> specifically says "Microsoft documents their compiler trap values".
Here's Geoff's article:
https://groups.google.com/group/comp.lang.c/msg/eeb8c91036919e10?dmode=source&output=gplain&noredirect
The "compiler trap values" that Microsoft documents are not the same
thing as C "trap representations" (that's probably why they have
a *different name*, and Geoff merely said that they're *analagous"
to C trap representations. For example, "Clean Memory" is filled
with 0xCD bytes, which can easily represent a valid value for some
type (certainly for unsigned char).
>>> Me: "Nice summary! Say, isn't there another one, 0x0000000C, as a
>>> [non-C] trap for [non-C] null pointers? I don't remember..."
>>>
>>> C: "Oh no, that wouldn't be a [C] null pointer."
>>>
>>> Me: "Yes, well I was talking about B's [non-C] trap values. I see a
>>> Microsoft debugger catch these things and call them [non-C] null
>>> pointers."
>>
>> I think you missed Geoff's point.
>
> I doubt it.
If you think Geoff was using the phrase "null pointer" or "trap
representation" to refer to anything other than a null pointer
or trap representation as defined by the C standard, then yes,
you missed Geoff's point.
"I see a Microsoft debugger catch these things and call them [non-C]
null pointers." -- I don't believe you have seen that.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-21 17:46 -0500 |
| Message-ID | <kdkgfv$hpd$1@dont-email.me> |
| In reply to | #30479 |
On 1/21/2013 16:32, Keith Thompson wrote: > Shao Miller <sha0.miller@gmail.com> writes: > >> So it is imprecise to say that such a value has a trap representation, >> because the behaviour is still well-defined. Otherwise, the last >> sentence of N1570's 6.5.3.2p4 is redundant: >> >> "If an invalid value has been assigned to the pointer, the behavior >> of the unary * operator is undefined.102)" > > No. Accessing an object with a trap representation has undefined > behavior. I don't understand this as an answer for "it is imprecise to say that such a value has a trap representation, because the behaviour is still well-defined." I don't understand it as an answer for "Otherwise, the last sentence of N1570's 6.5.3.2p4 is redundant." Did you think that I didn't think that accessing a trap representation was undefined behaviour? > What that means is that the behavior is not defined *by the C > standard*; see [N1570] 3.4.3, the definion of the phrase "undefined > behavior". Another entity can certainly define behavior for such > accesses. > That is true and is also not applicable to the case under discussion. > For example, (void*)0x0000000C is very likely a trap representation > under Windows NT. I don't know why you find that to be likely. Maybe I've just done too much x86? > The behavior of applying unary "*" to that value is > undefined, in the sense that the C standard does not define its > behavior. Windows NT can define the behavior if it likes; that doesn't > cause it to cease being a trap representation. > I am thankful for your patience with the discussion. I think I understand that what was missing in the discussion so far was "implementation-defined", which _also_ allows Windows NT to define the behaviour. >> But anyway, a pointer value pointing to no object can still be >> "trapped" by Windows during indirection and can still provide useful >> information to a Windows debugger. It just does not precisely match >> C's trap representation, for behavioural differences. > > Yes, it does. > No, it doesn't. :) The behaviour that is being discussed _is_ defined, _until_ the indirection. It is not undefined before that point. > I'm afraid that what you wish is irrelevant. Give me a break. How unfortunate it would be for Microsoft to market their compiler as "taking care of all your undefined behaviour needs!" Better confidence is possible. > It has undefined behavior. Maybe you're right (I've been wrong!), but I don't see why you believe that strongly enough to assert it. > [...more about undefined behaviour...] >> This was in regards to the lower part of his post where he >> specifically says "Microsoft documents their compiler trap values". > > Here's Geoff's article: > > https://groups.google.com/group/comp.lang.c/msg/eeb8c91036919e10?dmode=source&output=gplain&noredirect > > The "compiler trap values" that Microsoft documents are not the same > thing as C "trap representations" (that's probably why they have > a *different name*, and Geoff merely said that they're *analagous" > to C trap representations. For example, "Clean Memory" is filled > with 0xCD bytes, which can easily represent a valid value for some > type (certainly for unsigned char). > Did you think I meant something else? That is _precisely_ why I said it was a "Wonderful, wonderful summary!" That is why I was talking about this "analogous" thing, and not trap representations. I tried to clarify that a few times, but only managed to confuse. Sorry about that. >>>> Me: "Nice summary! Say, isn't there another one, 0x0000000C, as a >>>> [non-C] trap for [non-C] null pointers? I don't remember..." >>>> >>>> C: "Oh no, that wouldn't be a [C] null pointer." >>>> >>>> Me: "Yes, well I was talking about B's [non-C] trap values. I see a >>>> Microsoft debugger catch these things and call them [non-C] null >>>> pointers." >>> >>> I think you missed Geoff's point. >> >> I doubt it. > > If you think Geoff was using the phrase "null pointer" or "trap > representation" to refer to anything other than a null pointer > or trap representation as defined by the C standard, then yes, > you missed Geoff's point. > No, I don't think that. I have no idea why you might think that I think that. > "I see a Microsoft debugger catch these things and call them [non-C] > null pointers." -- I don't believe you have seen that. > "These things" == the subject that Geoff had most recently discussed: "[non-C] trap values". -- - Shao Miller -- "Thank you for the kind words; those are the kind of words I like to hear. Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-22 07:43 -0800 |
| Message-ID | <lnd2wx5iko.fsf@nuthaus.mib.org> |
| In reply to | #30484 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/21/2013 16:32, Keith Thompson wrote:
>> Shao Miller <sha0.miller@gmail.com> writes:
>>> So it is imprecise to say that such a value has a trap representation,
>>> because the behaviour is still well-defined. Otherwise, the last
>>> sentence of N1570's 6.5.3.2p4 is redundant:
>>>
>>> "If an invalid value has been assigned to the pointer, the behavior
>>> of the unary * operator is undefined.102)"
>>
>> No. Accessing an object with a trap representation has undefined
>> behavior.
>
> I don't understand this as an answer for "it is imprecise to say that
> such a value has a trap representation, because the behaviour is still
> well-defined." I don't understand it as an answer for "Otherwise, the
> last sentence of N1570's 6.5.3.2p4 is redundant." Did you think that I
> didn't think that accessing a trap representation was undefined behaviour?
I *think* the phrase "such a value" refers to a pointer value such as
(void*)0x0000000C, in a Microsoft Windows 32-bit environment. If you're
talking about something else, the following probably won't make much
sense.
Let's try a concrete example. Given this code snippet:
int *ptr;
uintptr_t x = 0x0000000C;
memcpy(&ptr, &x, sizeof ptr);
int deref = *ptr;
I assert that evaluating `*ptr` has undefined behavior. I also assert,
though with slightly less confidence, that after the memcpy() call ptr
contains a trap representation.
Do you disagree? If so, can you cite where the C standard defines the
behavior of the dereference?
[snip]
>> "I see a Microsoft debugger catch these things and call them [non-C]
>> null pointers." -- I don't believe you have seen that.
>
> "These things" == the subject that Geoff had most recently discussed:
> "[non-C] trap values".
What you've seen, as I recall, is the Microsoft debugger, on an
empt to dereference (on the machine code level) a pointer with
the representation 0x0000000C, printing an error message that
includes the identifier "NULL_CLASS_PTR_DEREFERENCE". That is not
the debugger calling 0x0000000C a null pointer. It's the debugger
inferring, from the attempt to dereference 0x0000000C, that there
was an attempt to dereference a C null pointer (0x00000000). Or am
I missing something?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 16:07 -0500 |
| Message-ID | <kdmv2g$g34$1@dont-email.me> |
| In reply to | #30505 |
On 1/22/2013 10:43, Keith Thompson wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>> On 1/21/2013 16:32, Keith Thompson wrote:
>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>> So it is imprecise to say that such a value has a trap representation,
>>>> because the behaviour is still well-defined. Otherwise, the last
>>>> sentence of N1570's 6.5.3.2p4 is redundant:
>>>>
>>>> "If an invalid value has been assigned to the pointer, the behavior
>>>> of the unary * operator is undefined.102)"
>>>
>>> No. Accessing an object with a trap representation has undefined
>>> behavior.
>>
>> I don't understand this as an answer for "it is imprecise to say that
>> such a value has a trap representation, because the behaviour is still
>> well-defined." I don't understand it as an answer for "Otherwise, the
>> last sentence of N1570's 6.5.3.2p4 is redundant." Did you think that I
>> didn't think that accessing a trap representation was undefined behaviour?
>
> I *think* the phrase "such a value" refers to a pointer value such as
> (void*)0x0000000C, in a Microsoft Windows 32-bit environment. If you're
> talking about something else, the following probably won't make much
> sense.
>
> Let's try a concrete example. Given this code snippet:
>
> int *ptr;
> uintptr_t x = 0x0000000C;
> memcpy(&ptr, &x, sizeof ptr);
> int deref = *ptr;
>
> I assert that evaluating `*ptr` has undefined behavior.
>
I'd say that it is implementation-defined behaviour; the implementation
knows
All I've been trying to point out is that, for Windows NT, 'ptr' does
not contain a trap representation, so any use _other_ than indirection
(via '*', '->', or function-call '()', for example) is well-defined.
For indirection, it depends on if 'ptr' points to an 'int' object, as
always.
Any confusion could be a matter of my not picking the right choice of
words at the right times.
> I also assert,
> though with slightly less confidence, that after the memcpy() call ptr
> contains a trap representation.
> Do you disagree? If so, can you cite where the C standard defines the
> behavior of the dereference?
>
Yes, I disagree with the second part about 'ptr' containing a trap
representation, for Windows NT.
" 6.2.6.1 General
1 The representations of all types are unspecified except as stated
in this subclause.
2 Except for bit-fields, objects are composed of contiguous
sequences of one or more bytes, the number, order, and encoding of which
are either explicitly specified or implementation-defined."
we don't see 'int *' explicitly specified, thereafter. For 32-bit
Windows NT, it so happens that this type is represented the same way as
an unsigned integer with all value bits. It so happens that 0xC is a
multiple of 'sizeof (int)' and represents a suitable alignment for an 'int'.
> [snip]
>
>>> "I see a Microsoft debugger catch these things and call them [non-C]
>>> null pointers." -- I don't believe you have seen that.
>>
>> "These things" == the subject that Geoff had most recently discussed:
>> "[non-C] trap values".
>
> What you've seen, as I recall, is the Microsoft debugger, on an
> empt to dereference (on the machine code level) a pointer with
> the representation 0x0000000C, printing an error message that
> includes the identifier "NULL_CLASS_PTR_DEREFERENCE". That is not
> the debugger calling 0x0000000C a null pointer. It's the debugger
> inferring, from the attempt to dereference 0x0000000C, that there
> was an attempt to dereference a C null pointer (0x00000000). Or am
> I missing something?
>
I don't think there needs to be an inference that were was a dereference
to a null pointer, but other than that, I think you're right. I really
wish I'd said "NULL_CLASS_PTR_DEREFERENCE" in the beginning, so it
wouldn't have been an issue of discussion. The trap values that Geoff
had discussed were not C trap representations, so I was likewise being
loose with "null pointers." I am filled with regret about that. As
we've already discussed, such a pointer value does not compare equal to
a C null pointer, so the debugger could hardly claim that it's a C null
pointer.
In order to understand what I mean by "loose" and why I might've done
so, for what it's worth, there are some people who don't use the C
definition for "null pointer" in non-pedantic discussion:
Scott Noone (well known at OSR Online):
http://social.msdn.microsoft.com/Forums/en-AU/windbg/thread/669a4137-f328-495f-a002-120fb6841542
Chad Bramwell:
http://www.altdevblogaday.com/2011/09/26/how-did-i-crash-in-that-func/
On 1/22/2013 11:01, Keith Thompson wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>> On 1/21/2013 18:50, Keith Thompson wrote:
> [...]
>>> I believe you've been implying that this means that 0x0000000c is
>>> a null pointer. It isn't. Seeing Philip's remark, quoted above,
>>> it's a little clearer why you might have thought so.
>>
>> I did not mean to imply that. Glen Herrmannsfeldt suggested a scenario
>> where that could be true, but I responded by saying that his case was
>> "along the lines that might be" the case I was talking about, which is
>> exactly true: The Microsoft debugger distinguishes between an invalid
>> pointer and an invalid pointer in the "null class". This implies that
>> the bits are significant and Glen's masking comes into play. It does
>> _not_ imply that that I'm saying 0x0000000C is a null pointer. If it
>> was confusing before, it should have been clear once I answered you
>> about it comparing as unequal with a null pointer. Sorry about the
>> confusion.
>
> You're inferring that the debugger message "NULL_CLASS_PTR_DEREFERENCE"
> refers to pointers in the "null class". I don't think that's what it
> means.
>
> Microsoft's development environment places a greater emphasis on C++
> than on C. An attempted dereference of address 0x0000000C is likely
> to result from an attempt to dereference a pointer to a class type
> (in C++, structs are classes), and the debugger may have more
> information that strengthens this inference.
>
> class foo {
> public:
> char x[12];
> int y;
> };
>
> foo* ptr = 0;
> int kaboom = ptr->y;
>
> (I just tried running a C++ program with the above code under MS Visual
> C++ 2010 Express, and didn't get that message; instead, I got "Unhandled
> exception at 0x009013a8 in null_class_ptr.exe: 0xC0000005: Access
> violation reading location 0x0000000c.".)
>
I get your point. I think another example would be a class method (or
whatever they're called) doing something with 'this->y'.
Off-topically, I'd suggest installing Debugging Tools for Windows for
messing around with Windows debugging; it's quite nifty! After an
error, '!analyze -v'.
On 1/22/2013 11:38, Keith Thompson wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
> [...]
>> The C semantics are defined by the Standard. A strictly conforming
>> program's behaviour is predictable, given these.
>>
>> Where we see a mention of implementation-defined subject matter, a C
>> program's behaviour is defined by both the C semantics as well as
>> implementation-specific definitions. The program's behaviour is
>> predictable, because the implementation documents their definitions.
>>
>> Where we see a mention of undefined behaviour, a C program's behaviour
>> is not guaranteed to be defined by any known means. The program's
>> behaviour is unpredictable, _unless_ we happen to know it by means
>> which aren't referred to by the Standard. An implementation or other
>> Standard (such as POSIX) can certainly define the behaviour.
>
> I agree with the above.
>
I'm glad to read that. :)
>> I'm trying to argue that case for undefined behaviour does not apply.
>
> Does not apply *to what*?
>
Considering a Windows pointer with representation 0xC, I meant with
regards to what Ben had asked about and what I had typed later in the
same post: "The C Standard _plus_ the implementation say: It can be
stored, read, passed, discarded, converted, compared, its size
determined, etc. Pretty well anything that doesn't involve using the
pointer for indirect access."
I would've added pointer arithmetic as allowed, but then I'd've had to
add a note about a complete object type. I would've added function
calls as not being allowed, but I hoped that would be understood by
"indirect access". An exhaustive list would be tedious.
> Can you provide a small self-contained program that's relevant to
> the point you're making?
>
> If you're saying that there's some construct whose behavior you
> say is implementation-defined, and I say is undefined, then please
> point out the construct in question in your program.
>
int main(void) {
void * vp1 = (void *) 0xC;
void * vp2 = vp1;
return 0;
}
This is implementation-defined, not undefined. If the implementation
does not define the result of the cast to be a trap representation, or
better yet, defines that pointers are implemented as unsigned integers
with all value bits, then there is no undefined behaviour. This is the
case for Windows NT, as far as I'm aware.
If someone wants to suggest that 'vp1' and 'vp2' have trap
representations, I'd like to know why. If we can agree that their
representations can provide hints to a debugger, then I'll be glad to
read that.
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-22 14:15 -0800 |
| Message-ID | <lnfw1s50ft.fsf@nuthaus.mib.org> |
| In reply to | #30525 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/22/2013 10:43, Keith Thompson wrote:
>> Shao Miller <sha0.miller@gmail.com> writes:
>>> On 1/21/2013 16:32, Keith Thompson wrote:
>>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>>> So it is imprecise to say that such a value has a trap representation,
>>>>> because the behaviour is still well-defined. Otherwise, the last
>>>>> sentence of N1570's 6.5.3.2p4 is redundant:
>>>>>
>>>>> "If an invalid value has been assigned to the pointer, the behavior
>>>>> of the unary * operator is undefined.102)"
>>>>
>>>> No. Accessing an object with a trap representation has undefined
>>>> behavior.
>>>
>>> I don't understand this as an answer for "it is imprecise to say that
>>> such a value has a trap representation, because the behaviour is still
>>> well-defined." I don't understand it as an answer for "Otherwise, the
>>> last sentence of N1570's 6.5.3.2p4 is redundant." Did you think that I
>>> didn't think that accessing a trap representation was undefined behaviour?
>>
>> I *think* the phrase "such a value" refers to a pointer value such as
>> (void*)0x0000000C, in a Microsoft Windows 32-bit environment. If you're
>> talking about something else, the following probably won't make much
>> sense.
>>
>> Let's try a concrete example. Given this code snippet:
>>
>> int *ptr;
>> uintptr_t x = 0x0000000C;
>> memcpy(&ptr, &x, sizeof ptr);
>> int deref = *ptr;
>>
>> I assert that evaluating `*ptr` has undefined behavior.
>
> I'd say that it is implementation-defined behaviour; the implementation
> knows
I disagree, and I'll elaborate below.
> All I've been trying to point out is that, for Windows NT, 'ptr' does
> not contain a trap representation, so any use _other_ than indirection
> (via '*', '->', or function-call '()', for example) is well-defined.
> For indirection, it depends on if 'ptr' points to an 'int' object, as
> always.
Assume that there is no int object at address 0x0000000C. Do you
believe that the behavior of an access to ptr is well-defined *by
the C standard*?
A trap representation is a representation such that accessing an object
holding it has undefined behavior. Undefined behavior is behavior that
is not defined by the C standard, regardless of whether the
implementation chooses to define it.
[...]
> I don't think there needs to be an inference that were was a dereference
> to a null pointer, but other than that, I think you're right. I really
> wish I'd said "NULL_CLASS_PTR_DEREFERENCE" in the beginning, so it
> wouldn't have been an issue of discussion. The trap values that Geoff
> had discussed were not C trap representations, so I was likewise being
> loose with "null pointers." I am filled with regret about that. As
> we've already discussed, such a pointer value does not compare equal to
> a C null pointer, so the debugger could hardly claim that it's a C null
> pointer.
And in fact it doesn't claim either that 0x000000C a C null pointer, or
that it's any kind of null pointer.
> In order to understand what I mean by "loose" and why I might've done
> so, for what it's worth, there are some people who don't use the C
> definition for "null pointer" in non-pedantic discussion:
>
> Scott Noone (well known at OSR Online):
> http://social.msdn.microsoft.com/Forums/en-AU/windbg/thread/669a4137-f328-495f-a002-120fb6841542
>
> Chad Bramwell:
> http://www.altdevblogaday.com/2011/09/26/how-did-i-crash-in-that-func/
I disagree with your interpretation of both linked discussions. In both
cases, there was a null pointer dereference in C (or C++) code, which
resulted in an attempted dereference of a non-null but invalid pointer
(similar to 0x0000000C) in the generated machine code.
Machine code *implements* C semantics; it needn't precisely mirror them.
[...]
> Considering a Windows pointer with representation 0xC, I meant with
> regards to what Ben had asked about and what I had typed later in the
> same post: "The C Standard _plus_ the implementation say: It can be
> stored, read, passed, discarded, converted, compared, its size
> determined, etc. Pretty well anything that doesn't involve using the
> pointer for indirect access."
Sure, but the C standard doesn't permit any of those things. It's well
known that an implementation can define behavior that isn't defined by
the C standard. Such behavior is still "undefined behavior" as defined
by 3.4.3.
[...]
>> Can you provide a small self-contained program that's relevant to
>> the point you're making?
>>
>> If you're saying that there's some construct whose behavior you
>> say is implementation-defined, and I say is undefined, then please
>> point out the construct in question in your program.
>
> int main(void) {
> void * vp1 = (void *) 0xC;
> void * vp2 = vp1;
> return 0;
> }
>
> This is implementation-defined, not undefined. If the implementation
> does not define the result of the cast to be a trap representation, or
> better yet, defines that pointers are implemented as unsigned integers
> with all value bits, then there is no undefined behaviour. This is the
> case for Windows NT, as far as I'm aware.
No, it's undefined. It may additionally be defined by the
implementation, but it's not implementation-defined.
The phrase "implementation-defined behavior", as defined by the C
standard, refers *only* to behavior that is explicitly referred to
by the standard as "implementation-defined". It doesn't just mean
"behavior that is defined by the implementation".
In your program, the behavior of the initialization:
void * vp2 = vp1;
is not defined by the C standard. For example, it could cause the
program to crash in a conforming implementation. It is therefore,
by definition, undefined behavior. If an implementation chooses
to define its behavior, that doesn't change any of the above --
and the implementation is not obligated to document its choice.
> If someone wants to suggest that 'vp1' and 'vp2' have trap
> representations, I'd like to know why. If we can agree that their
> representations can provide hints to a debugger, then I'll be glad to
> read that.
They are pointer values such that accessing them has undefined
behavior. They are neither null pointers, nor pointers to any
object, nor pointers just past the end of any object. It's not 100%
clear to me, from the standard's definition of "trap representation",
that they *must* be trap representations, but I believe that
they are.
Speculation: Perhaps what bothers you is the idea that "undefined
behavior" and "trap representation" imply "This is evil, don't
touch!!!". They don't. It's perfectly valid for an implementation
to define the behavior of something that has "undefined behavior" in
the standard, or to use a C trap representation for its own purposes.
Certainly their representation can provide hints to a debugger; we've
seen that demonstrated. That doesn't cause them not to be trap
representations.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-22 14:31 -0800 |
| Message-ID | <lnbocg4zp8.fsf@nuthaus.mib.org> |
| In reply to | #30544 |
Keith Thompson <kst-u@mib.org> writes:
> Shao Miller <sha0.miller@gmail.com> writes:
[...]
>> Considering a Windows pointer with representation 0xC, I meant with
>> regards to what Ben had asked about and what I had typed later in the
>> same post: "The C Standard _plus_ the implementation say: It can be
>> stored, read, passed, discarded, converted, compared, its size
>> determined, etc. Pretty well anything that doesn't involve using the
>> pointer for indirect access."
>
> Sure, but the C standard doesn't permit any of those things. It's well
> known that an implementation can define behavior that isn't defined by
> the C standard. Such behavior is still "undefined behavior" as defined
> by 3.4.3.
[...]
Sorry, that was imprecise. What I should have said is that the C
standard doesn't define the behavior of any of those things.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-22 21:32 -0500 |
| Message-ID | <kdni4e$sem$1@dont-email.me> |
| In reply to | #30544 |
On 1/22/2013 17:15, Keith Thompson wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>> On 1/22/2013 10:43, Keith Thompson wrote:
>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>> On 1/21/2013 16:32, Keith Thompson wrote:
>>>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>>>> So it is imprecise to say that such a value has a trap representation,
>>>>>> because the behaviour is still well-defined. Otherwise, the last
>>>>>> sentence of N1570's 6.5.3.2p4 is redundant:
>>>>>>
>>>>>> "If an invalid value has been assigned to the pointer, the behavior
>>>>>> of the unary * operator is undefined.102)"
>>>>>
>>>>> No. Accessing an object with a trap representation has undefined
>>>>> behavior.
>>>>
>>>> I don't understand this as an answer for "it is imprecise to say that
>>>> such a value has a trap representation, because the behaviour is still
>>>> well-defined." I don't understand it as an answer for "Otherwise, the
>>>> last sentence of N1570's 6.5.3.2p4 is redundant." Did you think that I
>>>> didn't think that accessing a trap representation was undefined behaviour?
>>>
>>> I *think* the phrase "such a value" refers to a pointer value such as
>>> (void*)0x0000000C, in a Microsoft Windows 32-bit environment. If you're
>>> talking about something else, the following probably won't make much
>>> sense.
>>>
>>> Let's try a concrete example. Given this code snippet:
>>>
>>> int *ptr;
>>> uintptr_t x = 0x0000000C;
>>> memcpy(&ptr, &x, sizeof ptr);
>>> int deref = *ptr;
>>>
>>> I assert that evaluating `*ptr` has undefined behavior.
>>
>> I'd say that it is implementation-defined behaviour; the implementation
>> knows
>
> I disagree, and I'll elaborate below.
>
>> All I've been trying to point out is that, for Windows NT, 'ptr' does
>> not contain a trap representation, so any use _other_ than indirection
>> (via '*', '->', or function-call '()', for example) is well-defined.
>> For indirection, it depends on if 'ptr' points to an 'int' object, as
>> always.
>
> Assume that there is no int object at address 0x0000000C. Do you
> believe that the behavior of an access to ptr is well-defined *by
> the C standard*?
>
Assuming you really meant "access to ptr" and not "access to *ptr", my
answer is: No, then no.
The first access is during the 'memcpy'. The implementation defines the
representations of both 'x' and 'ptr'. If they do not have the same
size, there could be an out-of-bounds condition. If they do have the
same size, then this access is fine and we move on.
The second access is during the lvalue conversion that determines the
operand of the unary '*' operator. This second access has
implementation-defined behaviour, since the implementation defines the
mapping from object representations to values. Anything not defined (by
omission) or explicitly defined to be a trap representation would be a
trap representation. In that case, the lvalue conversion would yield
undefined behaviour. Otherwise, the value is a valid value and we get
past that lvalue conversion.
After that point, we can fret about the '*' operator. Whether or not
there's an object at address 0xC is not a consideration until this
point, so my understanding goes.
What I would say is an extremely relevant piece of Standard has
accidentally been snipped:
" 6.2.6.1 General
1 The representations of all types are unspecified except as stated
in this subclause.
2 Except for bit-fields, objects are composed of contiguous
sequences of one or more bytes, the number, order, and encoding of which
are either explicitly specified or implementation-defined."
Until the indirection in the last line, your example above should have
no different expectation for undefined/defined behaviour when compared to:
#include <string.h>
#include <stdio.h>
int main(void) {
float f;
unsigned int x = 0x4048F5C3;
memcpy(&f, &x, sizeof x);
printf("%f\n", f);
return 0;
}
If you'd say that this is undefined behaviour rather than
implementation-defined behaviour, please do explain why.
> A trap representation is a representation such that accessing an object
> holding it has undefined behavior. Undefined behavior is behavior that
> is not defined by the C standard, regardless of whether the
> implementation chooses to define it.
>
Did you just say that implementation-defined behaviour is a subset of
undefined behaviour? I don't think you did, given that you discuss
"implementation-defined," down below.
I think you think that I'm arguing that there is undefined behaviour and
that it so happens to be defined by Microsoft, so I'm claiming it to be
"well-defined". I'm not! I'm saying that there are parts where the
Standard calls something "implementation-defined" instead of
"undefined", and this is one such instance.
I tried to explain this before with the three paragraphs in response to
Ben about "predictability." "Well-defined" to me means that either the
Standard defines it directly, or defines some of it and defines that an
implementation defines the rest of it. Undefined behaviour doesn't
match either of those, even if the implementation provides definitions.
Was that not clear?
> [...]
>
>> I don't think there needs to be an inference that were was a dereference
>> to a null pointer, but other than that, I think you're right. I really
>> wish I'd said "NULL_CLASS_PTR_DEREFERENCE" in the beginning, so it
>> wouldn't have been an issue of discussion. The trap values that Geoff
>> had discussed were not C trap representations, so I was likewise being
>> loose with "null pointers." I am filled with regret about that. As
>> we've already discussed, such a pointer value does not compare equal to
>> a C null pointer, so the debugger could hardly claim that it's a C null
>> pointer.
>
> And in fact it doesn't claim either that 0x000000C a C null pointer, or
> that it's any kind of null pointer.
>
I don't think it's intentional, but I'm going to share a result of this:
I've been contacted by another regular who has the impression that we've
been arguing for a long time about whether or not 0xC is a null pointer.
while (1) {
You("It's not a null pointer.");
Me("Well I didn't mean a C null pointer. Sorry.");
}
What do you mean by "any kind of null pointer"? After this discussion,
I didn't think it was remotely possible to believe that anything other
than the C definition could be spoken of. Heh.
There are at least 4 IDs that WinDbg uses for an invalid memory access:
1. BAD_PTR_DEREFERENCE
2. NULL_CLASS_PTR_DEREFERENCE
3. NULL_DEREFERENCE
4. STRING_DEREFERENCE
An exception can be analyzed (with 'analyze -v') and a "default bucket
ID" will be chosen by WinDbg. I seldom debug programs where it chooses
#1 or #4. I usually see it choose #2 or #3. A garbage pointer usually
just yields a default bucket ID "progtype_FAULT" (such as "DRIVER_FAULT"
or "APPLICATION_FAULT"), with no mention of "NULL" anywhere.
>> In order to understand what I mean by "loose" and why I might've done
>> so, for what it's worth, there are some people who don't use the C
>> definition for "null pointer" in non-pedantic discussion:
>>
>> Scott Noone (well known at OSR Online):
>> http://social.msdn.microsoft.com/Forums/en-AU/windbg/thread/669a4137-f328-495f-a002-120fb6841542
>>
>> Chad Bramwell:
>> http://www.altdevblogaday.com/2011/09/26/how-did-i-crash-in-that-func/
>
> I disagree with your interpretation of both linked discussions. In both
> cases, there was a null pointer dereference in C (or C++) code, which
> resulted in an attempted dereference of a non-null but invalid pointer
> (similar to 0x0000000C) in the generated machine code.
>
> Machine code *implements* C semantics; it needn't precisely mirror them.
>
I don't think you understood my interpretation.
Scott: "This is a NULL pointer dereference in NTFS."
Chad: "Once again we are dereferencing a NULL pointer and once again our
program is crashing..."
Chad: "...the real problem was that your pointer was NULL?"
Chad: "So there ya go. A whole lot of null dereferences..."
In none of the cases was 'NULL' dereferenced. In none of the cases was
"null pointer" typed. That is, people don't always say precisely what
they mean. I'll try to do better in the future.
> [...]
>
>> Considering a Windows pointer with representation 0xC, I meant with
>> regards to what Ben had asked about and what I had typed later in the
>> same post: "The C Standard _plus_ the implementation say: It can be
>> stored, read, passed, discarded, converted, compared, its size
>> determined, etc. Pretty well anything that doesn't involve using the
>> pointer for indirect access."
>
> Sure, but the C standard doesn't permit any of those things. It's well
> known that an implementation can define behavior that isn't defined by
> the C standard. Such behavior is still "undefined behavior" as defined
> by 3.4.3.
>
Discussed above. I'm claiming it's defined by the Standard to be
implementation-defined behaviour, not that it's
undefined-behaviour-relative-to-the-Standard and which happens to be
defined elsewhere. I could be wrong, as always, but I've yet to
understand why that might be.
> [...]
>
>>> Can you provide a small self-contained program that's relevant to
>>> the point you're making?
>>>
>>> If you're saying that there's some construct whose behavior you
>>> say is implementation-defined, and I say is undefined, then please
>>> point out the construct in question in your program.
>>
>> int main(void) {
>> void * vp1 = (void *) 0xC;
>> void * vp2 = vp1;
>> return 0;
>> }
>>
>> This is implementation-defined, not undefined. If the implementation
>> does not define the result of the cast to be a trap representation, or
>> better yet, defines that pointers are implemented as unsigned integers
>> with all value bits, then there is no undefined behaviour. This is the
>> case for Windows NT, as far as I'm aware.
>
> No, it's undefined. It may additionally be defined by the
> implementation, but it's not implementation-defined.
>
I don't understand this perspective, given 6.3.2.3p5:
"An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced type,
and might be a trap representation.67)"
> The phrase "implementation-defined behavior", as defined by the C
> standard, refers *only* to behavior that is explicitly referred to
> by the standard as "implementation-defined". It doesn't just mean
> "behavior that is defined by the implementation".
>
Yes, and that's the stuff I'm talking about. (See above.)
> In your program, the behavior of the initialization:
>
> void * vp2 = vp1;
>
> is not defined by the C standard. For example, it could cause the
> program to crash in a conforming implementation. It is therefore,
> by definition, undefined behavior. If an implementation chooses
> to define its behavior, that doesn't change any of the above --
> and the implementation is not obligated to document its choice.
>
You're talking about undefined behaviour. I'm talking about
implementation-defined behaviour. This line cannot stand on its own...
We have to ask, "Was the lvalue conversion of 'vp1' defined?"
The answer is, "Yes, because it has a valid value."
Then we ask, "How do we know that?"
The answer is, "Because it was initialized with the valid value that was
the result of the cast."
Then we ask, "How do we know the result of the cast was a valid value?"
The answer is, "Because the result of the cast conversion is
implementation-defined, and Microsoft's implementation defined it to be
a valid value."
If we'd encountered any lack of definitions along the way, there'd be
undefined behaviour. Or, more naturally, we could work from the
beginning, too. :)
>> If someone wants to suggest that 'vp1' and 'vp2' have trap
>> representations, I'd like to know why. If we can agree that their
>> representations can provide hints to a debugger, then I'll be glad to
>> read that.
>
> They are pointer values such that accessing them has undefined
> behavior. They are neither null pointers, nor pointers to any
> object, nor pointers just past the end of any object. It's not 100%
> clear to me, from the standard's definition of "trap representation",
> that they *must* be trap representations, but I believe that
> they are.
>
Well I suppose it's hard to prove either way, given that it's C90. I
just figured that it is up to the implementation to define which
representations map to which of {value, non-value}. I'm about C99%
sure, so learning otherwise would be a valuable learning experience.
> Speculation: Perhaps what bothers you is the idea that "undefined
> behavior" and "trap representation" imply "This is evil, don't
> touch!!!". They don't. It's perfectly valid for an implementation
> to define the behavior of something that has "undefined behavior" in
> the standard, or to use a C trap representation for its own purposes.
>
Good guess, but nope. :)
> Certainly their representation can provide hints to a debugger; we've
> seen that demonstrated. That doesn't cause them not to be trap
> representations.
>
Agreed.
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-23 17:17 -0500 |
| Message-ID | <kdpnhb$79e$3@dont-email.me> |
| In reply to | #30550 |
On 1/22/2013 21:32, Shao Miller wrote: > On 1/22/2013 17:15, Keith Thompson wrote: >> Shao Miller <sha0.miller@gmail.com> writes: >>> I don't think there needs to be an inference that were was a dereference >>> to a null pointer, but other than that, I think you're right. I really >>> wish I'd said "NULL_CLASS_PTR_DEREFERENCE" in the beginning, so it >>> wouldn't have been an issue of discussion. The trap values that Geoff >>> had discussed were not C trap representations, so I was likewise being >>> loose with "null pointers." I am filled with regret about that. As >>> we've already discussed, such a pointer value does not compare equal to >>> a C null pointer, so the debugger could hardly claim that it's a C null >>> pointer. >> Scott Noone suggested that I won't find any documentation for "NULL_CLASS_PTR_DEREFERENCE". D'oh well. :S -- - Shao Miller -- "Thank you for the kind words; those are the kind of words I like to hear. Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-23 19:49 -0500 |
| Message-ID | <kdq0fd$vjm$1@dont-email.me> |
| In reply to | #30583 |
On 1/23/2013 17:17, Shao Miller wrote: > On 1/22/2013 21:32, Shao Miller wrote: >> On 1/22/2013 17:15, Keith Thompson wrote: >>> Shao Miller <sha0.miller@gmail.com> writes: >>>> I don't think there needs to be an inference that were was a >>>> dereference >>>> to a null pointer, but other than that, I think you're right. I really >>>> wish I'd said "NULL_CLASS_PTR_DEREFERENCE" in the beginning, so it >>>> wouldn't have been an issue of discussion. The trap values that Geoff >>>> had discussed were not C trap representations, so I was likewise being >>>> loose with "null pointers." I am filled with regret about that. As >>>> we've already discussed, such a pointer value does not compare equal to >>>> a C null pointer, so the debugger could hardly claim that it's a C null >>>> pointer. >>> > > Scott Noone suggested that I won't find any documentation for > "NULL_CLASS_PTR_DEREFERENCE". D'oh well. :S > Experiment reveals that this ID is yielded from indirection on address 1 all the way through binary 10011111111/decimal 1279/hexadecimal 0x4FF; binary 10100000000/decimal 1280/hexadecimal 0x500 yields a different ID (for 32-bit Windows XP). These numbers don't appear to have anything to do with any C limits that I'm aware of. -- - Shao Miller -- "Thank you for the kind words; those are the kind of words I like to hear. Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Geoff <geoff@invalid.invalid> |
|---|---|
| Date | 2013-01-23 18:55 -0800 |
| Message-ID | <jk21g8lcof3799folfp0u9ba8f11dog7d6@4ax.com> |
| In reply to | #30583 |
On Wed, 23 Jan 2013 17:17:16 -0500, Shao Miller <sha0.miller@gmail.com> wrote: >Scott Noone suggested that I won't find any documentation for >"NULL_CLASS_PTR_DEREFERENCE". D'oh well. :S You won't find documentation on it. It's internal to Windbg. The bucketing codes are used by Windbg to determine the kind of debug report it generates. As far as I know, Microsoft has never documented these codes. The 0xC0000005 code, STATUS_ACCESS_VIOLATION, is enough to know you have a bad pointer somewhere and it's time to start unwinding the stack in the debugger to see how it happened. But all this is not C. I think this horse is muerto.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-24 11:01 -0800 |
| Message-ID | <ln7gn2v205.fsf@nuthaus.mib.org> |
| In reply to | #30550 |
Shao Miller <sha0.miller@gmail.com> writes:
[273 lines deleted]
> You're talking about undefined behaviour. I'm talking about
> implementation-defined behaviour. This line cannot stand on its own...
[53 lines deleted]
I'm planning to follow up on this Real Soon Now; I just haven't had time
lately. Funny how being employed cuts into your free time.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-24 14:11 -0500 |
| Message-ID | <kds10v$ogi$1@dont-email.me> |
| In reply to | #30618 |
On 1/24/2013 14:01, Keith Thompson wrote: > Shao Miller <sha0.miller@gmail.com> writes: > [273 lines deleted] >> You're talking about undefined behaviour. I'm talking about >> implementation-defined behaviour. This line cannot stand on its own... > [53 lines deleted] > > I'm planning to follow up on this Real Soon Now; I just haven't had time > lately. Funny how being employed cuts into your free time. > It sure does! Best wishes for success in your new role. No sweat about the discussion; week-ends sometimes work. :) -- - Shao Miller -- "Thank you for the kind words; those are the kind of words I like to hear. Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Geoff <geoff@invalid.invalid> |
|---|---|
| Date | 2013-01-22 17:51 -0800 |
| Message-ID | <hheuf8t51nin7enfkrooetupog50147p71@4ax.com> |
| In reply to | #30505 |
On Tue, 22 Jan 2013 07:43:51 -0800, Keith Thompson <kst-u@mib.org> wrote: >What you've seen, as I recall, is the Microsoft debugger, on an >empt to dereference (on the machine code level) a pointer with >the representation 0x0000000C, printing an error message that >includes the identifier "NULL_CLASS_PTR_DEREFERENCE". That is not >the debugger calling 0x0000000C a null pointer. It's the debugger >inferring, from the attempt to dereference 0x0000000C, that there >was an attempt to dereference a C null pointer (0x00000000). Or am >I missing something? You're not missing anything. That is precisely what is happening. The actual message is something like: "Unhandled exception at 0x01091000 in trap.exe: 0xC0000005: Access violation writing location 0x0000000c." Error 0xC0000005 is STATUS_ACCESS_VIOLATION, the memory could not be written or read. The process attempted to access memory outside its memory pool.
[toc] | [prev] | [next] | [standalone]
| From | Philip Lantz <prl@canterey.us> |
|---|---|
| Date | 2013-01-20 16:48 -0800 |
| Message-ID | <MPG.2b66301a5fcc93bb9896e8@news.eternal-september.org> |
| In reply to | #30412 |
Shao Miller wrote: > Keith Thompson wrote: > > Shao Miller writes: > >> > >> Which of these most closely resembles the pointer value 0x0000000C in > >> this Windows scenario?: > >> > >> 1. A trap representation for some pointer type, invoking UB when read > >> 2. A valid value for some pointer type; pointing to an object > >> 3. A null pointer; pointing to no object, invoking UB when dereferenced > >> > >> If it doesn't compare equal to 'NULL', then it doesn't appear to match > >> any of these. But if we can fuzz our way from Standard theory to > >> real-world practice, we might note some similarities to #3. > > > > It could easily be #1. For example, if a type `struct foo` has a > > member `bar` at offset 12 (0xC), and a `struct foo*` object `ptr` > > that has a null pointer value, then `&(ptr->bar)` could easily have > > a representation that looks like 0x0000000C. > > It could be #1, but it isn't #1 in this Windows scenario. Using such a > pointer value doesn't yield undefined behaviour until it's dereferenced. > It'll still compare as unequal with valid pointer values, can still be > assigned to a pointer, etc. The undefined behavior occurred when &ptr->bar was executed (with ptr equal to NULL). You cannot refer to the language definition to make sense of anything that happens after that.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-20 21:33 -0500 |
| Message-ID | <kdi9ea$42p$1@dont-email.me> |
| In reply to | #30425 |
On 1/20/2013 19:48, Philip Lantz wrote:
> Shao Miller wrote:
>> Keith Thompson wrote:
>>> Shao Miller writes:
>>>>
>>>> Which of these most closely resembles the pointer value 0x0000000C in
>>>> this Windows scenario?:
>>>>
>>>> 1. A trap representation for some pointer type, invoking UB when read
>>>> 2. A valid value for some pointer type; pointing to an object
>>>> 3. A null pointer; pointing to no object, invoking UB when dereferenced
>>>>
>>>> If it doesn't compare equal to 'NULL', then it doesn't appear to match
>>>> any of these. But if we can fuzz our way from Standard theory to
>>>> real-world practice, we might note some similarities to #3.
>>>
>>> It could easily be #1. For example, if a type `struct foo` has a
>>> member `bar` at offset 12 (0xC), and a `struct foo*` object `ptr`
>>> that has a null pointer value, then `&(ptr->bar)` could easily have
>>> a representation that looks like 0x0000000C.
>>
>> It could be #1, but it isn't #1 in this Windows scenario. Using such a
>> pointer value doesn't yield undefined behaviour until it's dereferenced.
>> It'll still compare as unequal with valid pointer values, can still be
>> assigned to a pointer, etc.
>
> The undefined behavior occurred when &ptr->bar was executed (with ptr
> equal to NULL). You cannot refer to the language definition to make
> sense of anything that happens after that.
>
Agreed; my mistake. I should not have typed "undefined behaviour," but
"unexpected behaviour." I guess it wasn't obvious that I was trying to
discuss a bit "outside the box" from the C definitions.
As you point out:
&ptr->bar
&((*ptr).bar)
^^^^------ C UB
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2013-01-21 09:23 -0800 |
| Message-ID | <kfnvcaq78my.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #30425 |
Philip Lantz <prl@canterey.us> writes: >> [snip] > > The undefined behavior occurred when &ptr->bar was executed (with ptr > equal to NULL). [snip] Actually just slightly before -- when ptr is a null pointer, evaluating ptr->bar is already undefined behavior.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-20 17:07 -0800 |
| Message-ID | <lntxqb738t.fsf@nuthaus.mib.org> |
| In reply to | #30412 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/20/2013 10:57, Keith Thompson wrote:
>> Shao Miller <sha0.miller@gmail.com> writes:
>>>
>>> Which of these most closely resembles the pointer value 0x0000000C in
>>> this Windows scenario?:
>>>
>>> 1. A trap representation for some pointer type, invoking UB when read
>>> 2. A valid value for some pointer type; pointing to an object
>>> 3. A null pointer; pointing to no object, invoking UB when dereferenced
>>>
>>> If it doesn't compare equal to 'NULL', then it doesn't appear to match
>>> any of these. But if we can fuzz our way from Standard theory to
>>> real-world practice, we might note some similarities to #3.
>>
>> It could easily be #1. For example, if a type `struct foo` has a
>> member `bar` at offset 12 (0xC), and a `struct foo*` object `ptr`
>> that has a null pointer value, then `&(ptr->bar)` could easily have
>> a representation that looks like 0x0000000C.
>>
>
> It could be #1, but it isn't #1 in this Windows scenario.
I believe it is.
> Using such a
> pointer value doesn't yield undefined behaviour until it's dereferenced.
Yes, it does. Concretely:
int main(void) {
struct foo {
char c[12];
int i;
};
struct foo *fptr = NULL;
int *iptr = &(fptr->i);
return 0;
}
The evaluation of the expression `&(fptr->i)` has undefined behavior.
If you disagree, please show me where the standard defines its
behavior.
If the observed behavior is that the representation 0x0000000C is stored
in `iptr`, that doesn't mean the behavior is defined.
> It'll still compare as unequal with valid pointer values, can still be
> assigned to a pointer, etc.
It happens to do so in the implementation we're discussing, and probably
in most implementations.
>> [...]
>>
>>> (By the way, I've asked in another forum about possible documentation
>>> for NULL_CLASS_PTR_DEREFERENCE, although I don't know if you or anyone
>>> else cares.)
>>
>> The name NULL_CLASS_PTR_DEREFERENCE wouldn't necessarily refer to
>> a *null pointer*.
>
> It depends on the definition. For the C definition, if it doesn't
> compare equal to 'NULL', then it's probably not a null pointer, as you
> pointed out earlier.
A pointer that doesn't compare equal to NULL *definitely* isn't a null
pointer, by the definition of pointer equality in N1570 6.5.9p6.
(Unless the program's behavior is undefined for other reasons, in which
case anything goes.)
> For WinDbg users, it probably is. Hopefully I'll
> find out just what Microsoft has to say about it.
I don't believe so. As far as I can see, the only evidence you've
presented that this thing is a "null pointer" is the identifier
"NULL_CLASS_PTR_DEREFERENCE".
What I believe that name implies is that the pointer value whose
representation looks like 0x0000000C was most likely created as
the result of a null pointer. It doesn't imply that 0x0000000C
is itself a null pointer. Nobody other than you is saying that.
(Unless you can produce some Microsoft documentation that uses the
phrase "null pointer" -- with no other words between "null" and
"pointer" -- to refer to such a pointer value.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
Page 3 of 5 — ← Prev page 1 2 [3] 4 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web