5

Fox example:

int* a = new int[10];
int* b = a;
int* e = a + 10;
delete[] a;
for (; b != e; ++b);

I know dereferencing invalid pointer would be UB. But how about just compare and increment?

Background

Here's a question, OP's adding elements inside a range-based for loop, which might cause the iterator become invalid. But he's adding elements to the vector in the end, after that the iterator'll be increased and compared, no dereference. Is it UB?

Community
  • 1
  • 1
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 2
    I think the temporal aspects of pointer validity are a bit of a muddled issue in C++14. [N4430](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4430.html) attempts to address some of that. – Kerrek SB Oct 11 '15 at 14:30
  • as long as you don't dereference these pointers I so no reason why whould it cause UB.. but anyway, if you don't plan on dereferencing these pointers, why would you need this loop in the first place? – David Haim Oct 11 '15 at 14:34
  • @KerrekSB Seems to be implementation-defined behavior? "Any other use of an invalid pointer value has implementation-defined behavior." – songyuanyao Oct 11 '15 at 14:35
  • 2
    I think the intention was to outlaw it. On segmented architecture (i'm looking at you, 286) loading an invalid pointer value into register could fault (the segment registers didn't like it). So pretty much any use of a deleted pointer was declared UB. But given such architectures have been consigned to the dustbin of history there has been recent discussion of relaxing this. It works fine on any processor you're actually likely to meet, of course. – Alan Stokes Oct 11 '15 at 14:35
  • 1
    @DavidHaim: The reason would the current wording in the standard. – Christian Hackl Oct 11 '15 at 14:36
  • @AlanStokes: The point of the question is not why pointer arithmetic is UB in general, but specifically arithmetic on pointer values that were once valid. – Kerrek SB Oct 11 '15 at 14:36
  • @Kerrek That's what I was attempting to address. Once the memory is freed it may no longer be possible to even load the pointer value - the segment value may no longer be valid if the whole segment was freed. (I've seen it happen.) – Alan Stokes Oct 11 '15 at 14:40
  • @DavidHaim I know it doesn't make sense, I just want to know could we affirm the special case of the question I linked is UB. – songyuanyao Oct 11 '15 at 14:42
  • Your example and the question linked is quite different. A push_back dereferences the iterator. – Captain Giraffe Oct 11 '15 at 14:45
  • @CaptainGiraffe `push_back` dereference what iterator? – songyuanyao Oct 11 '15 at 14:48
  • @songyuanyao In your own answer `for-range-declaration = *__begin;`. – Captain Giraffe Oct 11 '15 at 14:50
  • @CaptainGiraffe There's a condition `if ( i == 3 ) {`. So `push_back` will happen at the last time of loop, after the dereference. – songyuanyao Oct 11 '15 at 14:54
  • @AlanStokes, Do you mean that comparison of pointers on a segmented architecture would require the translation of segment:offset address into flat memory address before the comparison? – Andrey Nasonov Oct 11 '15 at 14:56
  • @songyuanyao That has nothing to do with pointers but rather the specification of ranged-based for stated in the initializer list in your own answer. – Captain Giraffe Oct 11 '15 at 15:05
  • @Andrey No, I don't. In protected mode the segments are arbitrary selectors and there is no meaningful ordering between pointers to different segments. Once a segment becomes invalid its selector value may no longer be loaded into a segment register. – Alan Stokes Oct 11 '15 at 15:28
  • @AlanStokes, But you don't need to load the selector value into a segment register to compare or modify the pointers. The comparison of pointers referring to different segments is impossible and invalid in user mode while the comparison of pointers referring to the same segment needs only offset comparison. – Andrey Nasonov Oct 11 '15 at 15:33
  • @Andrey An equality check traditionally compared the whole thing. And although the compiler might not load the selector it was free to do so. `delete p; q = p;` could be enough to fault. – Alan Stokes Oct 11 '15 at 17:12

0 Answers0