mfem: Potential bug when manipulating Vectors?
Hi,
I noticed this behavior when trying to write a new Riemann solver. I’m using GCC 9.1.0 with MFEM 4.4 installed through spack. Basically, if you add two vectors and assign to a third, you get a compiler error (fair enough). But if you subtract two vectors, you get no compiler error but end up getting a wrong result.
Vector A(5), B(5), C(5);
// Set some values in A and B
for (int i = 0; i < 5; i++){
A(i) = i;
B(i) = i*i;
}
// error: no match for ‘operator+’ (operand types are ‘mfem::Vector’ and ‘mfem::Vector’)
C = A + B;
// No compiler error, but incorrect result
C = A - B;
C.Print();
// Prints out -6 -6 -6 -6 -6
// No compiler error and correct result with expected behavior (i.e. no change in A)
C = A;
C -= B;
A.Print();
// 0 1 2 3 4
C.Print();
// 0 0 -2 -6 -12
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 18 (17 by maintainers)
As this is a very technical problem, let me quickly explain what the issue is. The vector class overloaded the indirection operator (i.e. operator*double()). Since the subtraction operator is not overloaded, the expression
Vector - Vector
is resolved by the compiler to the pointer arithmetic expressiondouble* - double*
. Note that expressions of typedouble* + double*
are not valid pointer arithmetic expressions (as explained in §8.5.6 of the C++ standard). This pointer difference the triggers the overloaded assignment operator on Vector.An MWE exhibiting this issue is given by:
Edit: Will was faster. 😃
Hi @varchasgopalaswamy,
In general, I wouldn’t recommend using expressions like
C = A - B;
withVector
s in MFEM. That this even compiles is actually becauseA
andB
are implicitly cast todouble *
, and soA - B
becomes a difference of pointers (integer type), which is then promoted todouble
, andC
is given that constant value.It’s probably better to work with explicit
for
loops.We could, an implementation would look like:
I don’t know if there are other such “dangerous” operators.
2B would be great for serac. If mfem provides those operator overloads, we would adopt them immediately and probably remove the expression template implementation.
This indicates that we should overload
operator-
with a static_assert so this fails at compile time, right?There are also helper functions like