Search code examples
c++eigen

Eigen Expression Debugging


I'm debugging a function that does some math with the Eigen library and am getting different results on different platforms. I don't see anything obviously wrong but I'm really not that familiar with the library. I've pulled the local variables out into a simple test application. hitRight ends up true on Mac and Windows but not on Linux. While debugging I figured out that putting .eval() at the end of the "auto rightDistance" line resolves the problem but I'd really like to understand why.

#include <stdio.h>

#include "eigen/Eigen/Core"

using namespace Eigen;

int main()
{
    Vector2i p = Vector2i(302,12);
    int mTabControlWidth = 20;
    Vector2i mPos = Vector2i(0,0);
    Vector2i mSize = Vector2i(310,24);

    auto rightDistance = (p - (mPos + Vector2i(mSize.x() - mTabControlWidth, 0))).array();
    bool hitRight = (rightDistance >= 0).all()
    && (rightDistance < Vector2i(mTabControlWidth, mSize.y()).array()).all();
    if (hitRight)
        printf("Hit Right\n");

    printf("Hit none\n");

    return 0;
}

Solution

  • Vector2i(mSize.x() - mTabControlWidth, 0) gets destructed at the next ;, while rightDistance still refers to it. That is undefined behavior, i.e., with some luck it works like you expect, but it might do whatever the compiler wants to do (most likely crash or return arbitrary results).

    As Avi said, just avoid the auto. In your case, you should also use Array2i instead of Vector2i. This saves you from writing all the .array(). Also, if the auto expression worked, rightDistance would be evaluated twice instead of once (o.t.o.h, compiler are usually good at optimizing that away).

    int main()
    {
        Array2i p(302,12);
        int mTabControlWidth = 20;
        Array2i mPos(0,0);
        Array2i mSize(310,24);
    
        Array2i rightDistance = (p - (mPos + Array2i(mSize.x() - mTabControlWidth, 0)));
        bool hitRight = (rightDistance >= 0).all() && (rightDistance < Array2i(mTabControlWidth, mSize.y())).all();
        if (hitRight)
            printf("Hit Right\n");
    
        printf("Hit none\n");
    
        return 0;
    }