Code: Select all
<bochs:7> c
01991983900e[CPU0 ] write_linear_xmmword_aligned(): #GP misaligned access
bzt
Code: Select all
<bochs:7> c
01991983900e[CPU0 ] write_linear_xmmword_aligned(): #GP misaligned access
Accessing beyond the end of an array is undefined behavior.bzt wrote:Forget UB,
A few years ago, a friend of mine tried to access an array in an undefined way. He found gcc produced code to copy the entire array out of the way, make the write, and copy the array back! Granted, my friend had the unnecessary (i hope!) expectation that two arrays would be consecutive in memory, but the incident rather put me off using gcc and, by association, llvm. Not that I particularly wanted to use them before that.Octocontrabass wrote:Accessing beyond the end of an array is undefined behavior.bzt wrote:Forget UB,
I believe this, and I'm sorry, my comment was rather off-topic. To try to tidy up by way of explaining myself: when a C compiler shows it can generate code to copy an entire array under the surface, it seems shockingly un-C-like altogether! But, the more I think about it, the more my attitude seems like an artifact of a somewhat unrealistic view of C: that it does the absolute minimum under the surface. It might be "minimal" relative to many other high-level languages, but I have to admit it was producing 'invisible' code for type casting right from its inception. I suspect a lot of UB-creep-haters object to the addition of more such 'invisible' code.Solar wrote:This makes compilers and the binaries they produce more efficient.
Constructors, destructors, references, overloaded operators, .... the list of ways in which C++ can perform unexpectedly much work is staggering.Solar wrote:There is probably a very good explanation for why that compiler did what it did; because yes, C is all about the idea of not doing unnecessary or wasteful things "under the hood". (Likewise for C++, by the way, regardless of what Linus in his lack of understanding might claim...)
If any of those surprise you, it's not the fault of the language... what I was talking about is stuff like garbage collection or paying for features you don't use. Note that none of the features you mentioned actually introduce additional code or run-time cost when compared to doing the same things with C functions, or assembly. In the case of references, they save you the bother of checking for NULL...Constructors, destructors, references, overloaded operators...
Ugh! I'm the sort of person who wants to know all the "very good reasons". There's 4 things I can do with this:Solar wrote:There is probably a very good explanation for why that compiler did what it did; because yes, C is all about the idea of not doing unnecessary or wasteful things "under the hood".
Code: Select all
#include <string>
#include <cassert>
#include <cstdarg>
using namespace std;
void foo( std::string & parmN, ... )
{
va_list ap;
va_start( ap, parmN );
int i = va_arg( ap, int );
va_end( ap );
assert( i == 42 );
}
int main()
{
string broken;
foo( broken, 42 );
return 0;
}
Code: Select all
void sched_pick()
{
tcb_t *tcba = (tcb_t*)LDYN_tcbalarm;
ccb_t *ccb = (ccb_t*)LDYN_ccb;
uint i, nonempty;
do {
for(nonempty=false,i=PRI_SYS; i<PRI_IDLE; i++) {
if(ccb->hd_timerq && i==tcba->priority && tcba->alarmusec <= ccb->sched_ticks) {
sched_awake(tcba);
goto found;
}
if(ccb->hd_active[i]) {
nonempty = true;
if(ccb->cr_active[i] == 0) {
ccb->cr_active[i] = ccb->hd_active[i];
continue;
} else
goto found;
}
}
} while(nonempty);
...
found:
...
Code: Select all
ffffffffffe0ef40 <sched_pick>:
ffffffffffe0ef40: 31 c0 xor %eax,%eax
ffffffffffe0ef42: e9 59 fa ff ff jmpq ffffffffffe0e9a0 <sched_awake+0x290>
ffffffffffe0ef47: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
ffffffffffe0ef4e: 00 00
Code: Select all
ffffffffffe0ec80 <sched_pick>:
ffffffffffe0ec80: 55 push %rbp
ffffffffffe0ec81: 53 push %rbx
ffffffffffe0ec82: 48 83 ec 08 sub $0x8,%rsp
ffffffffffe0ec86: 48 8b 34 25 78 00 00 mov 0xffffffff80000078,%rsi
ffffffffffe0ec8d: 80
ffffffffffe0ec8e: 31 d2 xor %edx,%edx
ffffffffffe0ec90: 31 db xor %ebx,%ebx
ffffffffffe0ec92: eb 40 jmp ffffffffffe0ecd4 <sched_pick+0x54>
ffffffffffe0ec94: 0f 1f 40 00 nopl 0x0(%rax)
ffffffffffe0ec98: 48 8b 04 dd 88 00 00 mov -0x7fffff78(,%rbx,8),%rax
ffffffffffe0ec9f: 80
ffffffffffe0eca0: 48 8d 0c dd 00 00 00 lea 0x0(,%rbx,8),%rcx
ffffffffffe0eca7: 00
ffffffffffe0eca8: 48 85 c0 test %rax,%rax
ffffffffffe0ecab: 74 1d je ffffffffffe0ecca <sched_pick+0x4a>
ffffffffffe0ecad: 48 8b 14 dd c8 00 00 mov -0x7fffff38(,%rbx,8),%rdx
...
Did the code allow gcc to prove certain properties about tcba and ccb as always true (or false)?bzt wrote:WTF, hah? All the loops and queue head checks are gone! This is definitely changed semantics! No wonder that poor sched_awake() got random input! Even worse, this jumps into the sched_awake after the input verification!