1

Is this a clang bug?

#include <stdlib.h>
long func(int *p, long size) {
  int *q = (int*)realloc(p,size);
  if (p == q) {
    *p = 1;
    *q = 2;
    return *p + *q;
  }
  return 0;
}

func() returns 3 when realloc ends up not moving anything. This is obviously "wrong", but is it a bug?

realloc() return value aliases to nothing. But after verifying the pointer is identical, does this still hold?

Oded S
  • 273
  • 1
  • 4
  • It is not a bug. The value of p after the realloc call is indeterminate. – 2501 Oct 18 '16 at 11:14
  • What does that mean? I haven't heard that term before. – Oded S Oct 18 '16 at 11:17
  • @2501 Yes (if you mean `*p`, that is, `p` is passed by value and can't change), but if `p == q`, you can hardly speak of indeterminate. You're writing the 1 and 2 to exactly the same place of memory that is allocated for you. It should totally return 4. – The Vee Oct 18 '16 at 11:18
  • OK indeterminate is the same as "int i;" with automatic storage. – Oded S Oct 18 '16 at 11:19
  • @TheVee I guess it gets optimised – Kami Kaze Oct 18 '16 at 11:19
  • @TheVee No, the value of the pointer p is indeterminate. Read the standard or the linked answer. – 2501 Oct 18 '16 at 11:19
  • @KamiKaze But it's optimized a wrong way. If `p == q` (which the condition explicitly checks for!) then this should behave as `int k; k = 1; k = 2; return k + k;`. – The Vee Oct 18 '16 at 11:19
  • @TheVee: The C Standard, and the C++ standard, both agree that when realloc doesn't return a null pointer, the previous value is indeterminate. Comparing old and new pointer with == invokes undefined behaviour because one of them is indeterminate. From then on, anything can go wrong. That's part of the C and C++ language. – gnasher729 Oct 18 '16 at 11:20
  • OK indeterminate is the same as "int i;" with automatic storage. So, "p" (the pointer itself) has become indeterminate after it was passed to realloc()? Is this what the standard says? That sounds... odd – Oded S Oct 18 '16 at 11:20
  • @OdedS: That may sound odd to you, but that's exactly what happens and exactly what the standard says. – gnasher729 Oct 18 '16 at 11:22
  • @gnasher729 No, it's not. I'm reading the standard **right now** (7.22.3.5 of ISO/IEC 9899:2011) and there's nothing about a possible change of the *pointer*. Give me an exact citation if you have one. – The Vee Oct 18 '16 at 11:26
  • @OdedS To add to my first comment, the behavior of your function is undefined, which means that anything can happen. – 2501 Oct 18 '16 at 11:27
  • @2501 OK, it conforms to the standard as answered in the other question. – The Vee Oct 18 '16 at 11:39
  • @OdedS Out of curiosity: if you add an assignment `p = q` just after `if(p == q)`, does it return 4 now? Here you'd drop the "pointer to the old object", replace it by the "pointer to the new object" and access the latter. It's hard to imagine this is anything more than a no-op though... – The Vee Oct 18 '16 at 11:43
  • 1
    @TheVee indeed it changes nothing in the assembly except the "3" becomes "4". See for yourself https://godbolt.org/g/ZWRCiD – Oded S Oct 18 '16 at 14:03

0 Answers0