dimanche 28 novembre 2021

if condition with differing behaviour depending on a pre-evaluation or not

While doing a leetcode problem, I encountered a strange problem with vectors in C++ : an if-statement went directly to else even if the evaluated expression was evaluated true. Using VS debugger, I verified that this expression was true and really didn't understand why it worked like that. After some tests, I figured out a way to make it work : by evaluating THE SAME expression right before the if-statement and storing it in another variable, the if-statement worked as intended. I disassembled my code with VS debugger and found that that particular if-statement wasn't evaluated at all : at the end of the evaluation, I have a jmp instruction to the else part. Comparing with two other similar if-statements, I noticed they both have "je" or "jns" instead of that simple "jmp". As I don't know which compiler does leetcode use, I can't say if it's specific to Visual C++ compiler.
Does someone know why it works like this ? I'd like to understand better what's happening and what is my mystake even if I solved the code. My comprehension of assembly and compilers isn't good enough for the moment to figure out by myself.

Here is a simple code comparing three similar if-statements. The second one is not working.

#include <iostream>
#include <vector>

int main()
{
    std::vector<int>digits = { 9,9,9 };
    int i = 3;
    if (-1 < 0) {
        int k = 0; 
    }

    if ((digits.size() - 1 - i) < 0) {
        int k = 0;
    }
    else {
        int j = 0;
    }

    int test = digits.size() - 1 - i;
    if (test < 0) {
        int k = 0;
    }
    else {
        int j = 0;
    }
    return 0;
}

Here is the interesting parts in the disassemble ; the "unconditional jmp" I talked about is the instruction 00B83E03.

int i = 3;
00B83DDE  mov         dword ptr [i],3  
    if (-1 < 0) {
00B83DE5  mov         eax,1  
00B83DEA  test        eax,eax  
00B83DEC  je          main+0A5h (0B83DF5h)  
        int k = 0; 
00B83DEE  mov         dword ptr [ebp-30h],0  
    }

    if ((digits.size() - 1 - i) < 0) {
00B83DF5  lea         ecx,[digits]  
00B83DF8  call        std::vector<int,std::allocator<int> >::size (0B81190h)  
00B83DFD  sub         eax,1  
00B83E00  sub         eax,dword ptr [i]  
00B83E03  jmp         main+0BEh (0B83E0Eh)  
        int k = 0;
00B83E05  mov         dword ptr [ebp-3Ch],0  
    }
00B83E0C  jmp         main+0C5h (0B83E15h)  
    else {
        int j = 0;
00B83E0E  mov         dword ptr [ebp-48h],0  
    }

    int test = digits.size() - 1 - i;
00B83E15  lea         ecx,[digits]  
00B83E18  call        std::vector<int,std::allocator<int> >::size (0B81190h)  
00B83E1D  sub         eax,1  
00B83E20  sub         eax,dword ptr [i]  
00B83E23  mov         dword ptr [test],eax  
    if (test < 0) {
00B83E26  jns         main+0E1h (0B83E31h)  
        int k = 0;
00B83E28  mov         dword ptr [ebp-60h],0  
    }
00B83E2F  jmp         main+0E8h (0B83E38h)  
    else {
        int j = 0;
00B83E31  mov         dword ptr [ebp-6Ch],0  
    }

Thank you in advance !

Aucun commentaire:

Enregistrer un commentaire