#40 doc: mention the safeToReturn() logic

open
nobody
None
5
2012-06-02
2012-04-23
No

Here's a recipe to show how Blitz misbehaves with a call to a C++11 auto/decltype function:
Same results with recent versions of g++ and clang++

$ cat test.cpp
#include <blitz/array.h>
using namespace blitz;
struct cls
{
#define decltype_return(expr) -> decltype(expr) { return expr; }
auto half(const Array<double, 2> &B, const Range &i, const Range &j)
#ifdef SKIPHALF
decltype_return(B(i,j))
#else
decltype_return(.5 * B(i,j))
#endif

void substract_half(
const Array<double, 2> &A, const Array<double, 2> &B,
const Range &i, const Range &j
)
{ A(i,j) -= half(B,i,j); }
};
int main() {
Range i(0,2), j(0,4);
Array<double, 2> A(i,j), B(i,j);
A = 10;
B = 20;
cls op;
op.substract_half(A,B,i,j);
std::cerr << A << std::endl;
}

$ g++ -std=c++0x -DBZ_DEBUG -lblitz test.cpp
$ ./a.out
/opt/local/include/blitz/shapecheck.h:73 Incompatible shapes detected:
(3,5)
(1606416304,32767)

[Blitz++] Shape check failed: Module /opt/local/include/blitz/globeval.cc line 152
Expression: (s*A)
Assertion failed: (0), function _bz_evaluate, file /opt/local/include/blitz/globeval.cc, line 168.
Abort trap

$ g++ -std=c++0x -DBZ_DEBUG -lblitz test.cpp -DSKIPHALF
$ ./a.out
(0,2) x (0,4)
[ -10 -10 -10 -10 -10
-10 -10 -10 -10 -10
-10 -10 -10 -10 -10 ]

That is, if the half() function contains an expression including multiplication by a constant,
the array ranges seem to be uninitialised (i.e. the 1606416304 & 32767 values).

Quoting Patrik's comment from the mailing list:

That looks like it should work... It seems that somehow the expression
is not referring to B. You'll likely have to step through the
construction of the expression objects in the debugger to track this
one down. When it throws the assertion, what is the expression object
that it's trying to evaluate? It should contain a fastIterator object
pointing to your "B" array, but it obviously doesn't. The trick will
be to figure out why.

Discussion

  • Sylwester Arabas

    As explained today by Patrik on the mailing list, the issue here is that "the array you're generating with B(Range) goes out of scope, so the expression is pointing to an array that no longer exists. There is a way to make the expression hold a *copy* of the Array instead of a reference by using the function safeToReturn(expr)."

    If I checked correctly this os not documented anywhere - renaming the issue to "mention the safeToReturn() logic in the documentation".

    Sylwester

     
  • Sylwester Arabas

    • summary: problem with function returning an expression --> mention the safeToReturn() logic in the documentation
     
  • Sylwester Arabas

    • summary: mention the safeToReturn() logic in the documentation --> doc: mention the safeToReturn() logic
     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks