James Kuyper
4/13/2011 10:49:00 AM
On 04/13/2011 05:21 AM, Noob wrote:
> Hello,
>
> I suppose the following code has undefined behavior?
>
> #include<string.h>
> #include<assert.h>
> typedef unsigned long ULONG;
C gives you a lot of freedom in the naming of identifiers, but it's
generally a good idea to accept well-established naming conventions, to
improve communication with other programmers. One of the most widely
used naming conventions is to reserve names that are all CAPITAL letters
for macros. I'd recommend 'ulong' for this typedef.
> struct msg
> {
> ULONG event;
> ULONG args[4];
> };
> void dispatch_msg(ULONG *argv, int argc)
> {
> struct msg foob;
> assert(0<= argc&& argc<= 5);
> memcpy(&foob, argv, argc * sizeof *argv); /*** UB here ?? ***/
No, this is not undefined behavior. Whether or not there's any padding
between event and args is merely unspecified. It's perfectly permissible
to copy only a portion of an object, and argc*sizeof *argv is guaranteed
to be less than sizeof foob. However, the contents of foob.args after
the memcpy() call may, in principle, be indeterminate; among other
possibilities, they may contain trap representations. Even if they have
non-trap representations, if there's any padding, they won't contain the
values you expect them to. But that's not undefined behavior, just
unspecified.
> /* send foob to the handler */
Whether or not this code has undefined behavior depends upon what the
handler does with it. Realistically, the results are unlikely to be good
if there's any padding.
> }
>
> I imagine a (nasty ;-) compiler implementation could insert
> padding between event and args in struct msg, making
True, though that's rather unlikely. Reasonable implementations seldom
(never?) insert padding for any reason other than alignment issues, and
that can't be a relevant issue in this case.
--
James Kuyper