News for hackers. Stuff that matters.
Re:C pointers are not hardware pointers by asveikau on Sunday March 06, 2016 @03:28PM (#11235385)
> The pointer p has indeterminate value after free(p), so the comparison invokes undefined behavior.

Is there a citation in the standard for this? Obviously all bets are off with being able to dereference p, but it makes no sense that free() could also modify the pointer itself, and I have a hard time justifying how any implementation would reasonably make comparing dangling pointers invalid.

I can even see a legit use case for it being valid.

    void *p, *q;

    p = q = malloc(n);
    /* ... */
    if (foo)
       q = malloc(n);
    /* ... */

    free(p);
    if (p != q)
       free(q);
Here we free q only if it was a different allocation from p... The fact that p was dangling at the free(q) line is immaterial. I guess it's not so bad to move the free(p) to the end of this code, but it's surprising to me that a sane language implementation would consider the above invalid.
Re:C pointers are not hardware pointers by rm445 on Sunday March 06, 2016 @04:29PM (#11235626)
Clause 6.2.4 of C11, paragraph 2:

> The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

Like you it seems a bit odd to me - perhaps to make the standard prepared for architectures, existing or otherwise, where pointer values have to be loaded in specific registers, and then trap if they contain values pointing to unallocated pages? (Without being dereferenced).

Re:C pointers are not hardware pointers by skissane on Sunday March 06, 2016 @04:54PM (#11235728)
Imagine the following possible architecture: every pointer contains a valid bit (V), which is initially set to 1. The V bit is checked on every pointer dereference, and dereferencing a pointer with V=0 traps. free(p) as well as freeing the memory pointed to by p, also sets p.V=0. Now, if you copied p earlier, the copy would still have V=1, and hence would now != the original pointer, even though the actual address stored inside the pointer is the same. So your sample code would end up doing a double free on p when foo is false.

We can question whether the design choices of such a CPU architecture are sensible or not, but I can certainly imagine such a design decision being made at some point in the last few decades. Indeed, if you look at the history of tagged memory architectures (e.g. Burroughs large systems, IBM System/38, Intel iAPX 432) - their tagged pointers are in the same spirit as what I've described here, except they used multiple bits instead of just one, and the tag bits were often stored in a distinct memory area from the actual pointer addresses (I don't know how C implementations on those platforms - if they existed - actually handled free() or pointer comparison though.) I guess, the possibility of such a design decision motivates making this undefined behaviour in the C standard.

Re:C pointers are not hardware pointers by dllthomas on Monday March 07, 2016 @12:39AM (#11237323)
Except that free is defined to be a function, so it can't really make changes to arguments passed by value.
Re:C pointers are not hardware pointers by skissane on Monday March 07, 2016 @06:25AM (#11238294)
In general you are correct that C function arguments are passed by value. However, in the case of free() specifically, an implementation which treated the argument of free() as if it were passed by reference would be conforming. Obviously one cannot write a free() implementation in standard C with this behaviour, but there is no requirement that a conforming implementation's standard library functions such as free() have to be written in standard C (or indeed in C at all.)

As rm445 quoted C11 clause 6.2.4 para 2, "The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime". Hence, prior to free(p), p had a determinate value, now it has an indeterminate value. The standard imposes no requirement that it has the same value as it had before (indeed, such a requirement would contradict the explicit statement that the value is now indeterminate.) Any reliance on p having some particular value post free(p) is relying on undefined behaviour, and in undefined behaviour one is allowed to do anything at all, including giving free(p) pass-by-reference argument handling.

Re:C pointers are not hardware pointers by dllthomas on Tuesday March 08, 2016 @12:44AM (#11243736)
While I'm not sure there's no language preventing call-by-reference semantics around the pointer value, I agree that you could not distinguish without invoking undefined behavior, so it probably doesn't matter any.

Interestingly, the free() might poison not only the pointer passed in but all identical pointers as well.

This seems to allow us to implement pointers with two hops - the bits stored in a pointer value indexing into a lookup table that contains the actual address of the object. In that case, free could manipulate that table, invalidating existing pointers.

Re:C pointers are not hardware pointers by jsnell on Sunday March 06, 2016 @04:11PM (#11235559)
Consider an extreme segmented CPU architecture where the malloc implementation allocates a new segment for every object, free deallocates the segment, and the architecture has been defined such that any use of a stale segment descriptor is an error.
Re:C pointers are not hardware pointers by asveikau on Sunday March 06, 2016 @04:36PM (#11235661)
> and the architecture has been defined such that any use of a stale segment descriptor is an error.

Even trying to imagine such an architecture, it's hard to see that comparing pointers constitutes "use" - it seems more likely that this would just wind up being an integer comparison.

Re:C pointers are not hardware pointers by jsnell on Sunday March 06, 2016 @05:50PM (#11235970)
But that's just the point, in a segmented architecture pointers are not simply integers, and they can't be compared as such either. A pointer will be the combination of a segment descriptor of some sort and an offset. It would be completely reasonable for a pointer comparison to require that both segment descriptors are valid (e.g. maybe multiple distinct segment descriptors can map to the same physical segment, so pointer comparison needs to dereference the descriptor).
Re:C pointers are not hardware pointers by asveikau on Tuesday March 08, 2016 @10:31AM (#11245795)
When thinking of segmented architectures my mind jumps to 16-bit x86. Of course those are integers. It's common to store pointers in a 32bit value where half is segment and half is offset. A comparison of linear addresses would take segment * 16 + offset. No need to use the segment for that calculation.

Obviously it could be different for something more exotic, but I had a hard time seeing how it wouldn't eventually lead to or map well to integers.

Re:C pointers are not hardware pointers by maxhou on Sunday March 06, 2016 @06:29PM (#11236134)
Re:C pointers are not hardware pointers by nostrademons on Sunday March 06, 2016 @04:02PM (#11235528)
http://blog.llvm.org/2011/05/what-every-c-programmer-should-...

When behavior is undefined, the compiler can legally do anything up to and including formatting your hard drive or making your computer burst into flames. It's counterintuitive, but C compilers follow the C standard and not necessarily programmer's intuitions about C.

Re:C pointers are not hardware pointers by asveikau on Sunday March 06, 2016 @04:28PM (#11235620)
I asked for a citation about why this specifically is undefined, not a condescending lecture about what "undefined behavior" means.
Re:C pointers are not hardware pointers by dave2000 on Sunday March 06, 2016 @03:42PM (#11235441)
I think you're right. I also take issue with the "pointers point at an object, one byte into it or are null" statement. A pointer is a piece of memory/register that contains an address, and an address is just a bit pattern. 0 is an address, as is 1,2,3.... 0xffd9303e. It doesn't even have to be accessible memory; you can get all sorts of exciting effects if you write to or even read from addresses mapped to hardware but the datatype is still a pointer.
Re:C pointers are not hardware pointers by dllthomas on Sunday March 06, 2016 @03:48PM (#11235466)
My vague recollection of the relevant bits of the C standard has it that there are a few differences between how pointers to void, pointers to char, and pointers to anything else are treated in some respects. This might be one of them.

"A pointer is a piece of memory/register that contains an address, and an address is just a bit pattern."

This is true on virtually every modern system, but (if memory serves) not literally every system ever, and the C standard leaves room for some surprising things in some places. It would have been very nice if the author had actually included some references, though.

Re:C pointers are not hardware pointers by jibsen on Monday March 07, 2016 @02:57AM (#11237676)
Pointers to character types get some special treatment. They can be used to address the individual bytes of other objects (C11 6.3.2.3p7), and the strict aliasing rule allows character types to be used to access those bytes (6.5p7) (one interesting note is that uint8_t is not strictly required to be a character type [1]).

The problem with assuming things like a pointer working like an integer, is that compiler vendors may choose to start taking advantage of any undefined behavior and point to the standard if you complain.

[1]: https://gist.github.com/jibsen/da6be27cde4d526ee564

Re:C pointers are not hardware pointers by belovedeagle on Sunday March 06, 2016 @06:02PM (#11236032)
Seems like you missed the whole point of the article, which was that an abstract "pointer" is not the same thing as the bit field held in some register or memory location, any more than a Java Object is.
Re:C pointers are not hardware pointers by dave2000 on Sunday March 06, 2016 @08:07PM (#11236459)
So how does anything in this article add to my knowledge of c? I've been getting along just fine with the definition of pointers as agreed and employed by compilers and developers for a long time. This article appears part wrong, part obvious and part pointless.
Re:C pointers are not hardware pointers by netheril96 on Sunday March 06, 2016 @08:15PM (#11236486)
> This article appears part wrong, part obvious and part pointless.

Nothing in this article is wrong. What adds to your knowledge of C is that certain operations on C pointers that would make sense if they were just bit pattern are actually undefined behavior. Undefined behavior may lead to subtle bugs due to how compilers do optimizations.

Re:C pointers are not hardware pointers by dave2000 on Monday March 07, 2016 @05:53AM (#11238179)
I don't see how comparing the value of a pointer, the area of memory to which it points having been previously freed, is undefined behaviour. Is there a source in the spec for this?
Re:C pointers are not hardware pointers by belovedeagle on Wednesday March 09, 2016 @12:33AM (#11251132)
Yes, it's in the article.

> I don't see how [. . .] is undefined behaviour.

This is a perfectly meaningless sentence. "Undefined behavior" doesn't mean "things which don't make sense in a particular implementation", it literally means behavior not defined by the spec. The spec declines to define the meaning of p==q when p and/or q is a freed pointer. There's nothing to "see" here: it's just not defined.

Re:C pointers are not hardware pointers by TheCoelacanth on Monday March 07, 2016 @10:47AM (#11239475)
Did you miss the part where two pointers with identical bit patterns can compare not equal? E.g. in recent versions of gcc

    #include <stdio.h>

    int main(void)
    {
        int x, y;
        int *p = &x + 1;
        int *q = &y;
        printf("%p %p %d\n", p, q, p == q);
        return 0;
    }
prints

    0x7f7fffffdafc 0x7f7fffffdafc 0
Re:C pointers are not hardware pointers by botw on Monday March 07, 2016 @06:02PM (#11242440)
This is interesting. If this is true, then a lot of code based on the assumption p == q would be broken.