------- Comment #15 from rguenth at gcc dot gnu dot org 2010-08-11 11:37 ------- (In reply to comment #14) > No, you are not correct. The equivalent code to what I'm doing would be > something like: > > int buffer[4]; // 16 bytes on stack > buffer[0]=(int)&format > buffer[1]=(int)10 > buffer[2]=(int)&another_string > buffer[3]=(int)20 > call format_direct > > format_direct: > char** PTR4=(char**)&buffer[0]; > push PTR4 > call format_indirect > > format_indirect: > char** PTR4=get_from_stack // gets PTR4 as pushed in format_direct > printf("%s %d %s %d", > PTR4[0], // the same as (char*)buffer[0] > PTR4[1], // the same as (int)buffer[1] > PTR4[2], // the same as (char*)buffer[2] > PTR4[3] // the same as (int)buffer[3] > ); > > This code must work, obviously. There is no undefined behaviour, it is correct > and portable code, and well defined and established. Even if the machine is 16 > bits this would work without changes, just replace comment "16 bytes" by "8 > bytes" and name PTR4 to PTR2, if you like the cosmetic changes. > > I understand that when you look at your code you would call it undefined > behaviour, but your code is not the correct one: this one is. That is what > I've > been trying to explain. The calling convention states that the parameters > should be packed ajdacent, like I did in the struct above, and not as you did > in your example, and getting the address of the parameter should get the > address of the start of the buffer, as I did manually. > > Your code just ignored this and, of course, would not work (you don't even say > where you think the other parameters are). This is not an invention of mine, > or > something that only works when I'm lucky, packing all parameters adjacent to > each other is something the compiler really needs to do, so if it gives me the > correct address of the first parameter then this code works *always* and is > very portable. > > To show you that you are not correct I've done some changes to the source > file, > where I created a new function "format_direct2" that does something like this: > > void format_direct2(char* dst_buffer, int dst_buffer_size_bytes, const char* > format, ...) { > int buffer[3]; > buffer[0]=(int)format; > buffer[1]=(int)__DATE__; > buffer[2]=(int)__TIME__; > format_indirect(dst_buffer, dst_buffer_size_bytes, (const > char**)&buffer[0]); > } > > The new code works always, of course, since I'm the one ensuring that the > parameters are adjacent, and I'm the one selecting the correct address to pass > to "format_indirect". I am, in fact, manually generating the 2 requirements - > compliance with the calling convention and passing the correct address to > "format_indirect". It also works with GCC, of course, even when optimized (as > expected) and I attach the corresponding files. So, when optimized, you get > "format_direct2" to work correctly and "format_direct" causes a segmentation > fault (and it shouldn't). > > It would sure be interesting to see if you could quote some standard for C > which says that I'm not allowed to do this!!! I simply don't believe you can > find such text, or have I been wrong about C all my life and I can't use > pointers to navigate through buffers?? :-)
In the C language these implementation details are not exposed and thus not accessible. Hence your code invokes undefined behavior as you are trying to circumvent this impossibility. -- rguenth at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution| |INVALID http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249