This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: memcpy() inlining and alignment
- To: gcc-bugs at gcc dot gnu dot org, thorpej at netbsd dot org
- Subject: Re: memcpy() inlining and alignment
- From: Mike Stump <mrs at windriver dot com>
- Date: Fri, 3 Mar 2000 18:39:15 -0800 (PST)
> From: Jason Thorpe <thorpej@netbsd.org>
> Date: Fri, 03 Mar 2000 16:24:52 -0800
> I've recently been bitten by some unfortunate compiler behavior, and
> I would like your opinion as to whether or not this is a compiler
> bug or an application bug (in this case, code in the BSD TCP/IP
> stack).
I am sorry, it is a bug in your code, welcome to C and C++:
[#7] A pointer to an object or incomplete type may be
converted to a pointer to a different object or incomplete
type. If the resulting pointer is not correctly aligned56
for the pointed to type, the behavior is undefined.
Otherwise, when converted back again, the result shall
compare equal to the original pointer.
From C, and from C++ (from a working paper, the final standard I am
sure fixed the wording):
7 A pointer to an object can be explicitly converted to a pointer to an
object of different type.61) Except that converting an rvalue of type
pointer to T1 to the type pointer to T2 (where T1 and T2 are
object types and where the alignment requirements of T2 are no
stricter than those of T1) and back to its original type yields the
original pointer value, the result of such a pointer conversion is
unspecified.
which is totally botched, but luckily I know how to read it for you.
What we mean to say differently from the C language I posted, is that
the program will not dump core on the cast (C++ says it is
unspecified, not undefined), but that _if_ you use it, the exact value
it has is unspecified. Your code that assumes it knows what the value
is, is at best, not portable. In C, your code can dump (or do anything
it wants) at the point of conversion.
> Now, GCC can be configured to inline certain calls to memcpy(). However,
> we're encountering a case where this inlining of a memcpy() is causing
> unaligned accesses, because GCC apparently isn't taking into consideration
> that the source address (in this case) may not be aligned.
Right, we know that all pointers to an aligned type, must be pointed
to an aligned piece of data. This is a fantastic speed win. If you
lie to the compiler, you die. In your case, you claim to point to an
aligned piece of data, but in fact you don't, and we kill you for it.
Stop lying. If you use a pointer to an unaligned structure (see
attribute align), then you can win again:
#include <string.h>
struct s {
unsigned int a;
unsigned int b;
unsigned int i;
};
typedef __attribute__ ((packed, aligned (1))) struct {
unsigned int a;
unsigned int b;
unsigned int i;
} ust;
unsigned int
foo(unsigned char *cp)
{
ust *src;
struct s dst;
char *src1;
src = (void*)(cp + 1);
memcpy(&dst, src, sizeof(struct s));
return (dst.i);
}
Note, you can even play with the members in src this way, though, they
may be slow.
> (1) Is this a compiler bug, or is the code making the memcpy()
> call broken? I'm really hoping it's not the latter, since
> there is a LOT of code out there which assumes it can
> copy data from unaligned buffers into aligned buffers before
> accessing it.
This is a fine assumption, but, the _type_ must match the use. A
pointer to aligned data, must be be aligned, and a pointer to
unaligned data need not be.
> Date: Sat, 4 Mar 2000 02:20:19 +0100
> From: "Martin v. Loewis" <martin@loewis.home.cs.tu-berlin.de>
> I don't think so. In 7.12.2 of standard C, the description of memcpy
> is
> # The memcpy function copies n characters from the object pointed to
> # by s2 into the object pointed to by s1. If copying takes place
> # between objects that overlap, the behavior is undefined.
> There is no mentioning of alignment constraints, and it says that it
> is copying characters. So I think the compiler is wrong in assuming
> that it can inline the memcpy using word-size instructions.
You're half way there, now, prove the rest of his program is correct.
:-)