eval() of an rvalue DynamicMatrix returns an object which becomes garbage

Issue #133 wontfix
Mikhail Katliar created an issue

Example:

#include "blaze/Math.h"

#include <iostream>

using namespace blaze;


DynamicMatrix<double> f()
{
    return DynamicMatrix<double> {{1, 2}, {3, 4}};
}


int main(int, char **)
{
    auto const tmp = eval(f());

    // This line of code makes something on a stack so that tmp becomes garbage.
    // If it is commented then the tmp values look ok.
    std::cout << "***************" << std::endl;

    // Output tmp
    std::cout << tmp << std::endl;

    return 0;
}

Compile and run with

clang++ -I/path/to/blaze -std=c++14 test.cpp && ./a.out

Output

***************
( 1.42603e-105 1.06358e-259 )
(            3            4 )

If the 1st cout << line is commented, then the output is as one would expect

(            0            2 )
(            3            4 )

Comments (4)

  1. Klaus Iglberger

    Hi Mikhail!

    Thanks for raising this issue. Your observation is absolutely correct and can easily be reproduced. Unfortunately this behavior is unavoidable in an expression template framework. The eval() function returns a proxy object (also called expression object) that represents an operation on an operand. Using auto to store the operation is equivalent to defer the operation. If by the time the operation is executed the operand's lifetime has expired, the result is undefined behavior. Please see Scott Meyer's "Effective Modern C++", Item 6, for more information on this.

    From the example you use to demonstrate the problem we get the impression that you should use the evaluate() function instead of the eval() function:

    auto const tmp = evaluate( f() );
    

    Using evaluate() the given expression will be evaluated immediately, resulting in a matrix of the proper type. Please see the wiki for a detailed explanation of the difference between evaluate() and eval(). Thanks again for raising the issue,

    Best regards,

    Klaus!

  2. Mikhail Katliar reporter

    Hello Klaus,

    thank you very much for the detailed answer. I was not aware that there are two functions eval() and evaluate() and assumed that eval() would evaluate an expression to a Matrix object.

    Best regards, Mikhail

  3. Log in to comment