Компилятор Intel C++ не может обрабатывать глубокие шаблоны?

У меня есть проект на C++ с использованием библиотеки Marray. На данный момент он прекрасно компилируется и работает с MinGW g++ 4.7 и msvc2010 на Windows 7 x64, а также с g ++ 4.7 на Linux Mint x64. Я решил попробовать Intel C++ v. 12.1.4 для Linux. Он был в состоянии скомпилировать код, но когда он пытается выполнить любые шаблоны выражений, которые мешают работе строк (например, c = a + b, где все три члена являются матрицами), он ломается из-за ошибки сегментации. Эта проблема затрагивает как отладочную, так и выпускную версии приложения.

Я также попытался скомпилировать модульные тесты и учебный код для библиотеки Marray, и снова Intel C++ компилирует код, но не запускает его, если у него есть какие-либо шаблоны выражений. Действительно ли Intel C++ настолько плох с глубокими шаблонами или я что-то упустил? Нужно ли устанавливать какие-либо специальные флаги компилятора для работы шаблонных выражений? Или может быть что-то не так с конкретной библиотекой, которую я использую, а не с техникой шаблонов выражений в целом?

Я также пытался установить флаг -ftemplate-глубина- n, используя большое разнообразие от n до смехотворно больших значений 10^10, и все еще не имел успеха в запуске ни моего приложения, ни отдельных тестов / учебников по марриру без ошибки сегментации.

Upd.: Вот журнал gdb для tutorial-marray из упомянутой библиотеки, скомпилированный с icpc в режиме отладки.

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) 

Похоже, что проблема в основном не связана с техникой шаблонов выражений, арифметика с числами работает нормально. Проблема возникает, когда я пытаюсь добавить один массив в другой.

Upd. 2: Фактически все это похоже на проблему, упомянутую здесь. Решение должно быть в переписывании оператора E&() { return static_cast(*this); } в нечто вроде E& get_ref() { return static_cast(*this); } и то же самое для константной ссылки. И, конечно же, измените использование этих вещей в коде. Постараюсь, как только смогу, и сообщу о результатах.

1 ответ

Решение

Проблема похожа на ту, о которой сообщалось здесь. Фактическая причина проблемы заключается в том, что код, сгенерированный компилятором Intel C++, обрабатывает такие выражения:

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

как рекурсивные вызовы этого оператора. Простой обходной путь - заменить оператор на метод, подобный

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

Недостатком является то, что вы должны изменить каждую строку кода, который использовал этот оператор. К счастью, с упомянутой библиотекой Marray это было не так сложно, так что теперь и мое приложение, и учебные пособия, и модульные тесты этой библиотеки работают как компилятор с компилятором Intel C++.

Другие вопросы по тегам