We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello, Depending on the control #pragma pack(x), the result of the compilation is different. In C++, Here's the problem, but it is more difficult without picture:
With #pragma pack(2), the result is Ok.
TNetCv::TNetCv(void) { DCvPtrNetPtcl = Nil; .... Compiling give: 0x0801A95C 2000 MOVS r0,#0x00 0x0801A95E F8C40026 STR r0,[r4,#0x26] void TNetCvCOM::CvDoWhenNetEvent(ENUMNETEVENT TheCvEvent) { TNetCv::CvDoWhenNetEvent(TheCvEvent); // INHERITED switch(TheCvEvent) { case eNetEventRun: if (DCvPtrNetPtcl != Nil) DCvPtrNetPtcl->PtclDoWhenNetEvent(TheCvEvent); break; } } Compiling give: 97: if (DCvPtrNetPtcl != Nil) DCvPtrNetPtcl->PtclDoWhenNetEvent(TheCvEvent); 0x0801F782 F8D40026 LDR r0,[r4,#0x26] 0x0801F786 B128 CBZ r0,0x0801F794 0x0801F788 F8D40026 LDR r0,[r4,#0x26] 0x0801F78C 6801 LDR r1,[r0,#0x00] 0x0801F78E 6A0A LDR r2,[r1,#0x20] 0x0801F790 4629 MOV r1,r5 0x0801F792 4790 BLX r2
In both examples the offset of the pointer "DCvPtrNetPtcl" is 0x26
With #pragma pack(4), the result is Bad.
TNetCv::TNetCv(void) { DCvPtrNetPtcl = Nil; .... Compiling give: 0x0801A95C 2000 MOVS r0,#0x00 0x0801A95E F8C40026 STR r0,[r4,#0x26] void TNetCvCOM::CvDoWhenNetEvent(ENUMNETEVENT TheCvEvent) { TNetCv::CvDoWhenNetEvent(TheCvEvent); // INHERITED switch(TheCvEvent) { case eNetEventRun: if (DCvPtrNetPtcl != Nil) DCvPtrNetPtcl->PtclDoWhenNetEvent(TheCvEvent); break; } } Compiling give: 97: if (DCvPtrNetPtcl != Nil) DCvPtrNetPtcl->PtclDoWhenNetEvent(TheCvEvent); 0x0801F3FE 6AA0 LDR r0,[r4,#0x28] 0x0801F400 B120 CBZ r0,0x0801F40C 0x0801F402 6AA0 LDR r0,[r4,#0x28] 0x0801F404 6801 LDR r1,[r0,#0x00] 0x0801F406 6A0A LDR r2,[r1,#0x20] 0x0801F408 4629 MOV r1,r5 0x0801F40A 4790 BLX r2
Without changing a line of code Now, in the initialization is always offset 0x26, but in the second function the offset is 0x28. The result is an exception "UsageFault"
thank you for your help
Jean-François
Isn't that entirely to be expected?!
Technically, that almost certainly depends upon whether the code contains anything that might be affected by the pragma in question.
But IMO that is not really anything to do with the problem the OP is trying to illustrate, so it appears to me that your comment is irrelevant.
The OP said,
"Depending on the control #pragma pack(x), the result of the compilation is different ... Without changing a line of code"
So the OP expressed surprise that #pragma pack should alter the generated code.
The reason compilers insert packing is to make the code "easy" for the target architecture - by aligning data to whatever that architecture "prefers".
If you break that by forcing some other alignment using #pragma pack - or whatever - then it stands to reason that the compiler is going to have to adjust its output to accomodate your request.
Hence I think it reasonable to point out that a change should be expected - it should not be a surprise.
Further, great care is going to be needed that any pointer which points to a thing which has had its alignmend "messed-with" is fully aware of that, and does not just assume the "default" alignment - otherwise things like "UsageFaults" are to be expected...
And if I said that I thought a certain someone was annoyingly opinionated, would that be expressing surprise? or would it be expressing a fact?
Unless you are the OP, you don't really know whether he is expressing surprise or a fact in that sentence. To me, what he writes at the start is showing a fact and later he asks the question about the resultant code.
Unfortunately, I cannot provide specific help with his question and neither, it seems, can you.
My point is that you can't just arbitrarily change the alignment, and expect everything to "just work".
I can speak from experience, having tried it!
"... in contrast, taking the address of a field in a #pragma packed struct does not yield a __packed-qualified pointer. However, the field might not be properly aligned for its type, and dereferencing such an unaligned pointer results in Undefined behavior." (my emphasis)
http://www.keil.com/support/man/docs/armcc/armcc_cjadhedh.htm
I rest my case, m'lud.
IMO that depends on how the code is written in the first place.
Now if you expect your code to fail in this type of situation, it says more about your code, the way you write it and understanding of "how these things work".
Not at all. Assuming code works is what gives us all the broken software all around us. It is way better to assume the worst and spend a serious amount of time proving the code working.
Note this article: http://www.keil.com/support/man/docs/armcc/armcc_BABCFBHC.htm So how many thinks about properly attributing their pointers after they pack their data?
And it isn't part of the language standard. __unaligned is a similar keyword used by M$ to specify that a pointer points to unaligned data.
Assuming code works is what gives us all the broken software all around us.
Errrmmm. FYI prior to this sentence, I have not used the word assume in this thread!
Careful, inaccuracy is also a major cause of broken software.
And you haven't seen my make such a claim either. So back to you - and be careful with your assumptions.
Not at all.
Oh Per, how your style has changed over the years.
Maybe you should relax for a while. Maybe you could go for a walk in the woods. Maybe you'd be better to consider what you do and say. Maybe it would be best not to assume that where you go is free of traps.
Enjoy the rest of the weekend ;)
So - why is it so important for you to move the focus away from packed/unaligned data?
Important? Not to me. But, there again, importance is a relative term.