Question

I have a project in C++ using marray library. For now it compiles and runs quite fine with MinGW g++ 4.7 and msvc2010 on Windows 7 x64 and also with g++ 4.7 on Linux Mint x64. I decided to give a try to Intel C++ compiler v. 12.1.4 for Linux. It was able to compile the code but when it tries to execute any line bothering expression templates (like c = a + b where all three terms are matrices) it breaks down with segmentation fault. This issue affects both debug and release versions of the app.

I also tried to compile unit tests and tutorial code for marray library and again, Intel C++ compiles the code but fails to run it if it has any expression templates. Is Intel C++ really as bad with deep templates or am I missing something? Do I need to set any special compiler flags to make template expressions work? Or maybe it is just something wrong with the particular library I'm using, not the expression templates technique in general?

I also tried to set the -ftemplate-depth-n flag using a wide variety on n up to ridiculously large values of 10^10 and still had no luck in running neither my app nor marray unit tests/tutorial without the segmentation fault.

Upd.: Here is the gdb log for tutorial-marray from the mentioned library compiled with icpc in debug mode.

GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/dmitry/SOFT/Development/marray_orig/tutorial-marray...done.
(gdb) l 126
121                 size_t shape[] = {3, 4, 2};
122                 marray::Marray<int> a(shape, shape + 3, 2);
123                 marray::Marray<int> b(shape, shape + 3, 2);
124                 marray::Marray<int> c;
125
126                 ++a;
127                 --a;
128
129                 a += 2;
130                 a -= 2;
(gdb) break 126
Breakpoint 1 at 0x452de8: file /home/dmitry/SOFT/Development/marray_orig/marray/src/tutorial/tutorial.cxx, line 126.
(gdb) run
Starting program: /home/dmitry/SOFT/Development/marray_orig/tutorial-marray 
A(c,r,0) =
1 0 0 
0 0 0 
0 0 0 
0 0 0 

A(c,r,1) =
0 0 0 
0 0 0 
0 0 0 
0 0 2 

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 

Breakpoint 1, main () at /home/dmitry/SOFT/Development/marray_orig/marray/src/tutorial/tutorial.cxx:126
126                 ++a;
(gdb) next
127                 --a;
(gdb) next
129                 a += 2;
(gdb) next
130                 a -= 2;
(gdb) next
131                 a /= 2;
(gdb) next
132                 a *= 2;
(gdb) next
134                 c = a + b;
(gdb) next

Program received signal SIGSEGV, Segmentation fault.
0x0000000000420fcf in marray::ViewExpression<marray::View<int, false, std::allocator<unsigned long> >, int>::operator marray::View<int, false, std::allocator<unsigned long> > const& (this=0x7fffffffcd88)
at /home/dmitry/SOFT/Development/marray_orig/marray/include/marray/marray.hxx:5409
5409            { return static_cast<const E&>(*this); }
(gdb) 

Looks like the problem doesn't originate from the expression template technique in general, array arithmetics with numbers works fine. The problem arises when I'm trying to add one array to another.

Upd. 2: Actually the whole thing looks quite like the problem mentioned here. The solution should be in rewriting operator E&() { return static_cast(*this); } into something like E& get_ref() { return static_cast(*this); } and the same thing for const reference. And, of course, change the usage of these things within the code. Will try it as soon as I can and report the results.

Was it helpful?

Solution

The problem is similar to the one reported here. The actual reason of the issue is that the code generated by Intel C++ compiler handles expressions like this:

operator E&() 
{ 
    return static_cast<E&>(*this); 
}

as recursive calls of this operator. A simple workaround is to change the operator into method like

E& get_ref()
{
    return static_cast<E&>(*this);
}

The drawback is that you have to change every line of code which used that operator. Fortunately, it wasn't too hard with the mentioned marray library, so now both my app and the tutorials and unit tests of that library work like a charm with Intel C++ compiler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top