![]() |
alignment
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! |
Re: alignment
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. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) |
Re: alignment
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? -- Kies |
Re: alignment
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. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) |
Re: alignment
Kies Lee wrote:
> 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(). |
Re: alignment
> 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 ? -- Kies |
Re: alignment
Kies Lee wrote:
>> 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? </OT> > I don't > know why ? Neither do I. > -- > Kies > Cheers Vladimir -- My e-mail address is real, and I read it. |
Re: alignment
Kies Lee <lleelm@gmail.com> wrote:
> 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. -- :wq ^X^Cy^K^X^C^C^C^C |
Re: alignment
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. -- Flash Gordon Living in interesting times. Although my email address says spam, it is real and I read it. |
Re: alignment
"Kies Lee" <lleelm@gmail.com> writes:
>> 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. -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst> We must do something. This is something. Therefore, we must do this. |
| All times are GMT. The time now is 01:11 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.