alignment

K

Kies Lee

Hi everyone! I have a problem about the bus error.
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
Somebook said that it would cause a bus error for the alignment
problem.But I find it can run well.
What is the problem? Is there something wrong with me? Thank you!
 
R

Richard Heathfield

Kies Lee said:
Hi everyone! I have a problem about the bus error.
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
Somebook said that it would cause a bus error for the alignment
problem.

It could, yes. It might and it might not. The behaviour is undefined, since
p is not guaranteed to be a valid pointer (for, as you say, alignment
reasons).
But I find it can run well.

One of the possible outcomes of undefined behaviour is whatever it is that
you naively expected to happen - and of course an infinite variety of
behaviours that are minor or major variations on what you expected to
happen.
 
K

Kies Lee

I can't understand your meaning exactly. I think it will cause a bus
error, but it not. Is your meaning that the result depands on the
system or the compiler?
 
R

Richard Heathfield

Kies Lee said:
I can't understand your meaning exactly. I think it will cause a bus
error, but it not. Is your meaning that the result depands on the
system or the compiler?

Yes. The C language does not guarantee what will happen.
 
T

Tim Prince

Kies said:
Hi everyone! I have a problem about the bus error.
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
Somebook said that it would cause a bus error for the alignment
problem.But I find it can run well.
What is the problem? Is there something wrong with me? Thank you!
This would be expected to be quite slow, on current hardware platforms
which can make it work. Not that you would notice if you did it only
once. Besides, if it does "work," how can you check that it does the
same thing on all the platforms of interest to you? I suppose, for many
little-endian platforms, it would set u.a[1] to 17, and zero out
u.a[2..4]. The effect on u.i would depend on what was there before. On
a long-ago platform I learned on, it would (efficiently) zero out
u.a[0..2], and set u.a[3] and u.i to 17, without affecting u.a[4].
What's the point, other than to check how your platform behaves in odd
situations? You could do it more efficiently, portably, and readably,
with a simple assignment and a memset().
 
K

Kies Lee

main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
This would be expected to be quite slow, on current hardware platforms
which can make it work. Not that you would notice if you did it only
once. Besides, if it does "work," how can you check that it does the
same thing on all the platforms of interest to you? I suppose, for many
little-endian platforms, it would set u.a[1] to 17, and zero out
u.a[2..4]. The effect on u.i would depend on what was there before. On
a long-ago platform I learned on, it would (efficiently) zero out
u.a[0..2], and set u.a[3] and u.i to 17, without affecting u.a[4].
What's the point, other than to check how your platform behaves in odd
situations? You could do it more efficiently, portably, and readably,
with a simple assignment and a memset().

I don't want to know how it work, but I want to know why it works.
Because the address of the p(pointer) could be 3221217958(one possible
value),
it is not on the edge of the memory(cann't be divided by 4). I don't
know why ?
 
V

Vladimir S. Oka

Kies said:
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
This would be expected to be quite slow, on current hardware platforms
which can make it work. Not that you would notice if you did it only
once. Besides, if it does "work," how can you check that it does the
same thing on all the platforms of interest to you? I suppose, for many
little-endian platforms, it would set u.a[1] to 17, and zero out
u.a[2..4]. The effect on u.i would depend on what was there before. On
a long-ago platform I learned on, it would (efficiently) zero out
u.a[0..2], and set u.a[3] and u.i to 17, without affecting u.a[4].
What's the point, other than to check how your platform behaves in odd
situations? You could do it more efficiently, portably, and readably,
with a simple assignment and a memset().

I don't want to know how it work, but I want to know why it works.

If you learn how it works, you'll also find out why it works -- or not,
as the case may be depending on the implementation/host system.
Because the address of the p(pointer) could be 3221217958(one possible
value),
it is not on the edge of the memory(cann't be divided by 4).

<OT>
Apart from this being entirely irrelevant, I'm wondering why the fact
that X is not divisible by 4 ensures it cannot be on the edge of memory?
I don't
know why ?

Neither do I.

Cheers

Vladimir
 
I

Ico

Kies Lee said:
Hi everyone! I have a problem about the bus error.
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
Somebook said that it would cause a bus error for the alignment
problem.But I find it can run well.
What is the problem? Is there something wrong with me? Thank you!

This actually is off-topic on comp.lang.c, since your question is highly
implementation and/or processor specific. Your `problem' is probably
caused by a CPU which has special support for handling unaligned data:
when it tries to access *p, a special function in the CPU is triggered
that handles this transparantly for you by doing multiple aligned memory
accesses, altough it is often much slower then proper aligned access.
This is called a 'trap'. If you want more information about this, find a
newsgroup or mailinglist that is dedicated for your CPU or platform and
ask your question there.

But still : what you are doing here is not valid in C, so it is not safe
to expect this to work (or not work) in any way, C does *not* guarantee
anything in this case. Just don't do it.
 
F

Flash Gordon

Kies Lee wrote:

Please provide context for your posts, there is no guarantee that the
person reading it has seen what you are replying to. See
http://cfaj.freeshell.org/google/ for details on how to do this.

By chance, I happen to remember that this was a possibly unalligned
access to an in caused by casting a char* to an int*
I can't understand your meaning exactly. I think it will cause a bus
error, but it not.

That is one reason why you should not rely on it doing what you expect
when there is undefined behaviour.
> Is your meaning that the result depands on the
system or the compiler?

Not only is it compiler and system dependant, it also depends on what
options you give some compilers, what version of the compiler and, if
the author of the implementations is feeling nasty, the day of the week.

When you invoke undefined behaviour (which is what an unaligned access
does if the system requires an aligned access) the C standard says that
*anything* is valid, and there is no requirement for the behaviour to
have any form of consistency.
 
K

Keith Thompson

Kies Lee said:
main(void) {
union { char a[10];
int i;
} u;
int *p = (int*)&(u.a[1]);
*p = 17;
}
This would be expected to be quite slow, on current hardware platforms
which can make it work. Not that you would notice if you did it only
once. Besides, if it does "work," how can you check that it does the
same thing on all the platforms of interest to you? I suppose, for many
little-endian platforms, it would set u.a[1] to 17, and zero out
u.a[2..4]. The effect on u.i would depend on what was there before. On
a long-ago platform I learned on, it would (efficiently) zero out
u.a[0..2], and set u.a[3] and u.i to 17, without affecting u.a[4].
What's the point, other than to check how your platform behaves in odd
situations? You could do it more efficiently, portably, and readably,
with a simple assignment and a memset().

I don't want to know how it work, but I want to know why it works.
Because the address of the p(pointer) could be 3221217958(one possible
value),
it is not on the edge of the memory(cann't be divided by 4). I don't
know why ?

As far as the C language is concerned, what you're doing is invoking
undefined behavior. The standard doesn't say, and doesn't need to
say, anything more than that. The possible effects, as the standard
joke around here goes, include demons flying out of your nose.

The reason the authors of the C standard decided to make this
undefined behavior is that the actual result can differ widely on
different systems. It would have been possible to define a consistent
behavior and enforce it across all C implementations, but that would
have caused problems for some implementations. Instead, in certain
areas, each implementation is permitted to do whatever is most
natural, and leads to the most efficient code, for that particular
implementation.

If you have an odd address and try to read a 4-byte integer at that
address, one of several things can happen:

- You can get the full 4-byte integer from that address, if the
underlying hardware happens to support it. This might be slower
than for an aligned address, or it might not.

- You can get the full 4-byte integer from that address via some
kind of software support. For example, the attempt to read the
value can cause a system trap, and the memory management code in
the operating system can respond to the trap by reading the
value one byte at a time. This is likely to be much slower than
reading from an aligned address.

- You can get a full 4-byte integer, but not the one you were
expecting. I've worked with a system that simply ignores the
low-order bits of a misaligned address.

- You can get a system trap that crashes your program.

- You can get some other result that I haven't thought of.

Most of these things depend on the underlying hardware and/or
operating system. Any requirement for some particular behavior on
unaligned accesses would slow down *aligned* accesses on some systems,
making all programs slower.

For anything that the standard says is undefined behavior, you're
*never* guaranteed anything in particular; you can't assume that
you'll get a bus error, a segmentation fault, or anything else. The
system won't catch your error; it's entirely up to you to avoid making
the error in the first place.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top