简体   繁体   中英

Why does this example of what compilers aren't allowed to do cause null pointer dereferencing using cmov?

C code:

int cread(int *xp) {
    return (xp ? *xp : 0);
}

assembly code: (from a textbook example of what a compiler isn't allowed to do) using conditional move instruction

movl    $0, %eax
testl   %edx, %edx
cmovne  (%edx), %eax

This is an example used in Computer Systems: A Programmer's Perspective (2nd edition) to show that code cannot be compiled using conditional data transfer if either branch of a condition results in an error. In this case, the error would be the null pointer dereferencing of xp.

I understand that xp is dereferenced, but I don't understand how xp becomes a null pointer. Wouldn't that depend on pointer being passed as a parameter into the function?

The assembly code is technically valid, but it would fault if the input was NULL and as such doesn't match the behavior of the C code. Given that the whole point of the thing is to return zero in that case and not fault, it's wrong. The C equivalent is:

int cread(int *xp) {
    int val = *xp;
    return (xp ? val : 0);
}

As you can see, it first dereferences xp and only then checks to see if xp is NULL so this clearly won't work for NULL input.

If you make the call

cread(0);

The cmovene instruction will seg fault because it evaluates *xp even though the value will never be used.

In the assembly language, this is expressed by (%dx) . Ie the contents of the address in %dx are taken regardless of the value of dx .

The value of cmov has been called into question generally. For example Linus Torvalds is not a fan.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM