Summary: | Aliasing problems with user-defined operator new | ||
---|---|---|---|
Product: | gcc | Reporter: | Andreas Glowatz <Andreas.Glowatz> |
Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED DUPLICATE | ||
Severity: | normal | CC: | arno, gcc-bugs, rasmus.bonnedal |
Priority: | P2 | Keywords: | wrong-code |
Version: | 3.3.1 | ||
Target Milestone: | 3.4.0 | ||
Host: | i686-linux-gnu | Target: | i686-linux-gnu |
Build: | i686-linux-gnu | Known to work: | |
Known to fail: | Last reconfirmed: | ||
Attachments: | single C++ source file, ii file and g++ -v -save-temps output |
Description
Andreas Glowatz
2003-08-14 07:47:27 UTC
Created attachment 4603 [details]
single C++ source file, ii file and g++ -v -save-temps output
I noticed this wrong behaviour since version 3.3. In version 3.2.1, it seems to be ok. I can confirm this on the mainline but I think you are violating aliasing rules (confirmed but also using -fno-strict-alasing and running the program). I'm not sure that this is really an aliasing problem. The only casts that happen in the program involve char*s. I'd like an aliasing expert to look at this first. W. I tried using "-O3 -fno-strict-aliasing" and it seems to be ok, now. Is this the solution, or is there any more. Here's a reduced testcase. It returns 1 when compiled with "g++ -O2" and 0 when compiled with "g++ -O2 -fno-strict-aliasing": ================================================ char Pool[32]; struct A { A* next; }; A* a=0; struct B { void* p; B() : p((void*)4711) {} void* operator new(unsigned) { if (!a) a = (A*)Pool; A* q = a; a = a->next; return q; } }; int main () { new B; return a == (void*)4711; } ================================================ I'm not sure whether this example violates aliasing rules, but it's an aliasing problem nevertheless. I updated the summary accordingly. This looks like an almost exact dup of bug 11973. From that bug: Your code is invalid. What you do is this: - in new a->X_alc() you call C::operator new, which returns a C* which you later access - however, C::operator new calls alc(), which returns the memory location of an object which the compiler assumes is of type SList Such type games violate C++'s type aliasing rules. The solution is either to fix your code, or if you want to play hide-and-seek with the compiler, use -fno-strict-aliasing. The names of the functions are different but the game is the same. *** This bug has been marked as a duplicate of 11973 *** I'd like to reopen this bug report again, for the same reason as before: here we are only dealing with char*, which is special. We still need to have someone with more knowledge of aliasing rules here. W. Simple situation: If function is not inlined it works correct. If function is inlined it swaps 2 operations across this function and the calling one (operator new). Inlining should NEVER change net result in such cases. What's wrong with this code exactly ? Yuri (yuri@tsoft.com) Not a bug. The provided testcase violate alias rules. The compiler assume that the two pointers, 'this' and 'a' in this->p = 4711 (inside constructor) and a = a->next (inside new operator) point to different object, which is not true in your code. *** Bug 14822 has been marked as a duplicate of this bug. *** Confirmed again to be invalid. What happens here is that the underlying char[] is accessed first through a A* (within operator new) and later through a B* (in B's constructor). This is equivalent to: float foo(void) { char buf[64]; int* p1 = (int*)buf; float* p2 = (float*)buf; *p1 = 123; return *p2; } This code breaks aliasing rules (confirmed by Segher Boessenkool and Paul Brook), so the whole PR is invalid. *** Bug 15295 has been marked as a duplicate of this bug. *** Reopening to ... |