------- Comment #22 from rogerio at rilhas dot com  2010-08-11 17:15 -------
(In reply to comment #19)
> (In reply to comment #18)
> > Of course vsnprintf was my first choice, as you can see from the WIN32 part 
> > of
> > the code I sent you. In WIN32 I can use vsnprint in a very natural and
> > predictable way in "format_indirect". In LINUX this cannot be used in
> It's Linux (or GNU/Linux) not LINUX.

It is probably Win32, not WIN32. But thanks for the info.

> > "format_indirect" as GCC does not allow me to use vsnprintf on a function 
> > that
> > doesn't take variable parameters. 
> I explained why, see 7.15 in the C99 standard.


didn't need your explanations, I already knew it. That just shows you have been
missing the point from the start. I told why I didn't use vsnprintf, but you
seem to have missed it. Note that if I didn't need format_indirect to do the
actual work then I wouldn't have found any bug in GCC.

Maybe you are not realizing that format_indirect will not actually use
vanprintf, and will, instead, use my own parsing routines for several types of
parameters. The reason why I need a format_indirect is because I may have users
of my modules who are the ones that receive the variables parameters, and must
then pass the work on to my format_indirect to do the actual work.


> > I tried to bypass it specifying variable
> > parameters for "format_indirect", but of course the results are wrong 
> > because
> > GCC will have placed the wrong address in "format_address" inside
> > "format_indirect". So, in fact, vsnprintf will have exactly the same 
> > problem as
> > I had, and I would report exactly the same bug like I did.
> Not if you use it correctly, which you are not doing.
> void format_direct3(char* dst_buffer, int dst_buffer_size_bytes, const char*
> format, ...) {
>     va_list va;
>     va_start(va, format);
>     vsnprintf(dst_buffer, dst_buffer_size_bytes, format, va);
>     va_end(va);
> }


You missed the point again. I don't have any problem with any of the
format_direct functions if they were to do the actual formatting work. But they
are not. Many of our older software uses specific parameter parsing, so we
developed functions over the years to parse format strings ourselves with
specific parsing instructions. To reuse code as much as possible the work is
done in a format_indirect function that can be called by any of the several
format_direct functions.

If I could use format_direct I would have no problem and the GCC bug would not
bug me at all. But that would mean copying and maintainig our special
functionality which currently resides in one format_indirect function in
several (maybe dozens) of diferent format_direct functions.

You must have noted that I used va_start/va_end in my WIN32 example, so you
must be aware that I know how to use it. You must also be aware that in the
*Linux* :-) version I used snprintf instead, so you must have realized that I
already knew that I could not use va_start/va_end in the format_indirect
function.

Microsoft's compiler developers didn't see the need to limit use of
va_start/va_end inside format_indirect, so I was able to use it without any
problem. I tried it in GCC anyway but to no avail. I understood it and moved
on, you were the one to bring vsnprintf as a solution to format_indirect which
I pointed out to you was not a solution (the GCC bug persists). However, now
you know that the actual work is not done by vsnprintf.



> > As you can see I've tried very hard to explain all details of the problem, 
> > and 
> > why this is a bug in GCC.
> GCC claims to support C and C++.  Can you point to part of either standard
> which says your code is valid?


Yes, sure. Or, at least, I can get close enough since I'm not interested in
really making you believe that GCC would be a better product if it didn't mess
up the pair of requirements I mentioned before. I'll just leave you to believe
whatever you like.

The first thing to note is that GCC doesn't only claim to be a C/C++ compiler:
it claims it can produce cdecl calls. So I will have to go a little outside of
the scope of C99.

The GCC manual "http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc.pdf"; describes the
usage of cdecl as a possible option. Although not present in the code I sent
you I tried cdecl and stdcall specifiers and GCC didn't change anything in the
compiled code. This is the first suspicion that GCC is not conforming to what
it was supposed to do.

If GCC supports cdecl on a x86 plaform then it must support the packing of
parameters as defined for x86 (it is not standardize that I know of, but it is
well defined). I sugest reading
http://en.wikipedia.org/wiki/X86_calling_conventions for a number of references
on this parameter packing in the stack, one of my favorites is
"http://sco.com./developers/devspecs/abi386-4.pdf"; where you can read in
"Figure 3-48: C Stack Frame" how the parameters should be placed on the stack.
GCC would only be cdecl-compliant if it were to conform to this specification
(I believe it does, I believe the problem lies with the &format operation).

The C99 states in "6.5.3.2 Address and indirection operators", in point 3, that
"The unary & operator yields the address of its operand". So, relating this to
the cdecl placement, &format should inequivocally return the address where
format is on the stack, and no other address. Why? Because the "format"
variable is nowhere else but on the stack. There is no other address to return,
so not returning the real stack address is a bug. Can you find anything in C99
that says that there is an exception to this? Something along the lines of "you
can return an arbitrary address if the user requests the address of a function
parameter"? Or cand you find any other way to define &format that would make
this statement ambiguous?

About the pointer arithmetic, you can find references in C99 such as that in
6.5.6-8 where it is well shown that there is no undefined behaviour when
accessing arrays out of bounds. The text clearly says "Moreover, if the
expression P points to the last element of an array object, the expression
(P)+1 points one past the last element of the array object. In other parts you
can read that E1[E2] is the same as *((E1)+(E2)). Also, you can read the
defition for adding integers to pointers to realize that I was correct about
format_address[1] pointing to the 4-byte element after the format.

So, as you can see, my reasoning is well backed-up by standards and well
defined interfaces. The parameters should be nicely packed on the stack as
cdecl, and &format should return the address of the format on the stack. And,
contrary to what you say, pointer arithmetic past the boundaries of an array is
well defined. Can you find any standards that refute these conclusions?


> > You just keep dismissing all my arguments without any justification 
> > whatsoever.
> What you're doing is not defined by the C or C++ standard.


What I'm doing is not defined, but each step of my operation is. Just like
a=b+c/3-40 is not defined in C/C++ standards, but each of its individual
operations is.



> GCC is a C and C++ compiler. Can you show where in the C or C++ standards it
> says the stack must be laid out as you want?


Above you can see that my first operation is backed by a well defined cdecl
convention (although not standardized). Did GCC invent a new meaning for cdecl
based on the fact that is not standardized or does it conform to the well
defined meaning of cdecl as shown in the document I mentioned?

The other operation, &format, is also well defined and I showed you in C99
where to find it. I didn't read all the standard though, so I'm open to the
possibility that you show me where I can see in the standard that
&function_param is not applicable or defined. Note that I can pass literals to
functions, and inside I can always get the address of those literals placed on
the stack.

Pointer arithmetic to access out of bounds elements of arrays is also well
defined in C99, or can you find anywhere in C99 that P+1 will not point to the
next element if it is pointing to a location on the stack?


> > When you did justify I just proved your arguments to be false (no disrespect
> > intended) in the hope that this conversation would progress.
> > 
> > You don't explain why I can't rely on the calling convention to ensure the
> > parameters will be adjacent, 
> Because the C and C++ standards do not make any guarantees about layout of
> arguments in memory, so when using a C or C++ compiler to compile C or C++ 
> code
> you should not assume any particular layout.


Yes, you are right. That's why you would need to "step out of the C/C++" box
and realize that GCC also claims to be cdecl compliant. If you do that you will
realize that that implies a certain way to place parameters in memory. So I
would be able to reply on it, if it were done properly, as is the case with MS
compilers.


> > and you don't explain why I can't use &format to
> > get the address of that packed data on the stack. You just keep invoking 
> > some
> > standard where these 2 things are alledgedly not defined but without
> > materializing it (which I don't believe you can anyway!). You have not yet
> > shown why GCC is not required to place the parameters correctly on the 
> > stack,
> > and why GCC does not need to give me the true &format.
> The standard does not define how arguments are laid out, therefore it is
> undefined.


It is not undefined, I just showed you that. If you stick to C/C++ as the proof
that GCC has no bug then GCC should remove the claim that it is cdecl compliant
from its manuals.

If GCC is already cdecl compliant (as viewing disassembly code sugests) then
GCC has a bug in the &format statement, and that is clearly defined in the C99
standard.


> > So I'm stuck with your "you can't because you can't" replies and this
> > conversation will not progress any further, of course.
> The onus is on you to show where in the C standard it says that your code is
> well defined.  If the standard doesn't say it, it's not portable and not well
> defined.

I don't think the onus should be on my side. It shouldn't be so hard for me to
show you that GCC has a bug. I consider this to be way too obvious to justify
such reluctance from you to accept it.

You continuously laim it is not defined, yet I easilly showed that all my
claims are backed up by standards and well defined concepts.

You are the one who don«t seem to be making any effort to even understand the
importance of my report (as sugested by the quick way you sugested that I used
vsnprintf which is, by your own words, not applicable in format_indirect).

Anyway, that enough for me, I already spent way too much energy and time trying
to show you what I think should be obvious.


-- 


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

Reply via email to