-
Notifications
You must be signed in to change notification settings - Fork 280
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
7 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4215161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does it change anything?
Logically
(entry_mark[i].type == MZ_MOVE) && (i < entry_num)
<=>(i < entry_num) && (entry_mark[i].type == MZ_MOVE)
.Conjunction is commutative.
p ⋀ q ⇔ q ⋀ p
4215161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does it change anything? It's not about logic rules (this theory knows every software engineer, or at least I believe should know!!!). It's about avoiding
out of index
failure!Look at:
If
i is >= entry_num
then if you check(i < entry_num)
first, then it'sfalse
and we do not need to check rest of the condition (unless you really want to compile with flags forcing to check all condition terms).But if you check
entry_mark[i].type
andi is >= entry_num
then you will getnull pointer exception
orindex out of range
segfault, so checking(i < entry_num)
after(entry_mark[i].type == MZ_MOVE)
does not make sense.I hope it's clear
4215161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dare to disagree. This is diff of assembled zip.c-e14fef2-1 and zip.c-4215161-2.c"
It doesn't support your thesis.
There is a script attached to the post showing my point.
diff-4215161-2--e14fef2-1.zip
4215161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
outsider comment; feel free to ignore:
@tansy, I noticed that your script uses
-O2
for compilation. The optimizer likely saw the two conditions and concluded two things:(i < entry_num)
is easier to calculate than(entry_mark[i].type == MZ_MOVE)
(i < entry_num)
. if false, would invalidate the array access in(entry_mark[i].type == MZ_MOVE)
Running the compiler with
-g
instead reveals actual differences in the assembly. Feel free to analyze it for meaning, since I am not an assembly expert. Here is an excerpt; the rest is in the attached zip.diff-4215161-2--e14fef2-g.zip
4215161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tansy - what's your point? We do not have one assembler, one compiler and one operating system?
You can disagree, I'll not discuss it, it's up to you.
Look at the following silly code:
it prints:
Right?
Now, change the ordering in
if
statements toif (arr[i]->n == i && i < N) {
What would you get?
4215161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but every program has to be assembled before it will me compiled into machine code.
You're right. I didn't think it through (afer all, arguments have to be calculated first, before they will be used in expression, here: AND). It took me good few minutes to understand why it (your second and not first example) causes undefined behaviour.
It also implies that compiler doesn't do exactly what's been told, I mean does not perform logical AND. In assembler one can see it clearly - it does two comparisons and that's it. I guess it's how optimization works.
It also implies that in your example (
if (i < N && arr[i]->n == i)
) you don't mitigate UB either, but count on compiler's optimization; that it will do checki < N
first and jmp out before computing second argumentarr[i]->n == i
.--
Good point - that's true. I used -O2 as it what is used in real life.
Interestingly enough in kuba--'s example, using
-O2
optimization makes compiler to warn about UB,but using
-O0
doesn't, although executable segfaults anyways.