On Wednesday 07 November 2007, Julian Seward wrote: > > a real workaround would be to copy the content into a new location (e.g. > > a local variable) and access that one via its type. > I'd like to fix it properly, but there's lots of code like this: > > while (TC_(nextIterFM)( map_locks, (Word*)(void*)&gla, > (Word*)(void*)&lk )) { > ... > }
Ok, I`ve had a short look at the code and it seems that this is because of a generic AVL tree implementation based on "Lock" and a few other struct`s. Of course any casting you do here might silence the warning, but it does not fix the issue. The static type of the memory you allocated is "Lock". if you access it via "Word" (as the AVL implementation does), then you`re violating strict aliasing. For now this seems to work because the AVL implementation is not inline, so the compiler doesn`t have much chance at optimi^h^h^h^hscrewing it up. A proper solution would be something like typdef union { Word* asPtr; Word asWord; } AVLBase; and changing struct Lock into struct _Lock { AVLBase admin; ... Then the nextIterFM calls would look like: &TC_(nextIterFM)(map_locks, &gla.admin, &lk.admin) one could hide the ugly detail behind a #define, and it would suddenly look rather nice. Its a pity that type inheritance is not implemented in C ;) > > piece of memory via pointers that have a different type (except for the > > non-symmetrical char* exception). in this case I guess it is because > > Word* > char* exception? Does the standard say a char* can point at anything? not exactly. it is not about pointers, but about the actual access (load or store). The standard says that as an exception, you can read or modify any memory via "char" accesses (note, not unsigned/signed char! though that happens to work as well on almost any platform). The sole motivation behind that is that memcpy() has to work (which does not know type and is supposed to copy by char). so something like: int i = 0; char* p = (char*)&i; p[0] = 1; if (!i) abort(); is going to work. However, int i = 0; short* s = (short*)(void*)(char*)&i; s[0] = 1; if (!i) abort(); will not. So, by casting to "char*" inbetween, you`re silencing the warning (because that is implemented somewhere else in the compiler) but you`re not fixing the actual aliasing information (which is generated later). In this care, you`re still accessing memory that has the static aliasing information "struct _Lock" via "int". those two types may not alias. Even if you casted the pointer a hundred times inbetween to all kinds of different types, it does not matter: the actual access matters. In practice, it is possible that you confuse the compiler good enough so that it will stop "miscompiling" the code by no longer knowing that it doesn`t have to re-load a value that was already cached in a register, but any future version of the compiler might become better at interpreting your cast-chain. > If yes, can I use the same hack as I just committed, but with char* as > the intermediate type instead of void* ? No. Sorry for not following up earlier, I only got reminded of this email after I read the commit log. Greetings, Dirk ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Valgrind-developers mailing list Valgrind-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/valgrind-developers