------- 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

Reply via email to