------- Comment #14 from rogerio at rilhas dot com  2010-08-11 11:22 -------
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?? :-)


-- 

rogerio at rilhas dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45249

Reply via email to