Don’t create reference from pointer (part 1/2)

When programming in C++ (or any other language) you can sometime hit very weird behavior. Like your “if” statements are ignored. You usually find this the hard way. Like when your program crashes. You check the debugger and you see, that it crashes on null pointer inside “if”. Yes the “if” that checks for null pointers. Strange.
Well in this post I will try to explain what is happening to your program.

In C++ we have something called a reference. Reference is basically an alias to some value/object. This alias has several key points defined in standard. Like a reference has to be bound to a valid object in declaration.

This binding in declaration has the effect that reference can not be null. You will basically always create a valid reference because it is an alias to something. This has some consequences in compilation and especially in resulting assembly.

In compilation compiler can detect when you are doing something wrong and warn you. In resulting assembly the optimizer can omit some checks because it knows, that the object is valid.

A little example

This post is going to explain you why checks are ignored, when using references. First, however lets see a little sample code without references. You will see that the binary doesn’t contain the “if” we put there.

Check this simple code:

int doSomething();

int main( int argc, char** argv )
{
    int i = 5;

    if( i == 5 )
    {
        doSomething();
    }

    return 0;
}

This is the assembly result when no optimization is applied.

main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $32, %rsp
        movl    %edi, -20(%rbp)
        movq    %rsi, -32(%rbp)
        movl    $5, -4(%rbp)
        cmpl    $5, -4(%rbp)
        jne     .L2
        call    _Z11doSomethingv
.L2:
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc

This is with -O3 passed to GCC compiler

main:
.LFB0:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        call    _Z11doSomethingv
        xorl    %eax, %eax
        addq    $8, %rsp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc

As you can see the compiled just completely ignored the “if” in the optimized build. Why? Because it knows, that the “if” will always evaluate to true.

This simple code and compiled assembly showed that compiler do some analysis based on what it knows. The same will apply to references. More on that in the second part of this article.

Leave a Reply

Your email address will not be published. Required fields are marked *