1

marrayライブラリを使用した C++ のプロジェクトがあります。今のところ、Windows 7 x64 上の MinGW g++ 4.7 および msvc2010 で、また Linux Mint x64 上の g++ 4.7 で、非常にうまくコンパイルおよび実行されます。Linux 用の Intel C++ コンパイラ v. 12.1.4 を試してみることにしました。コードをコンパイルすることはできましたが、式テンプレート (3 つの項すべてが行列である c = a + b など) に悩まされている行を実行しようとすると、セグメンテーション違反で失敗します。この問題は、アプリのデバッグ バージョンとリリース バージョンの両方に影響します。

また、marray ライブラリーの単体テストとチュートリアル・コードをコンパイルしようとしましたが、インテル C++ はコードをコンパイルしますが、式テンプレートがある場合は実行に失敗します。インテル® C++ は深いテンプレートで本当に悪いのでしょうか? それとも何か足りないのでしょうか? テンプレート式を機能させるには、特別なコンパイラ フラグを設定する必要がありますか? それとも、一般的な式テンプレートの手法ではなく、使用している特定のライブラリに何か問題があるのでしょうか?

また、 -ftemplate-depth- nフラグをnにさまざまな値を使用して10^10 という途方もなく大きな値まで設定しようとしましたが、セグメンテーション違反なしでアプリも marray ユニット テスト/チュートリアルも実行できませんでした。

Upd .:これは、デバッグ モードで icpc を使用してコンパイルされた前述のライブラリからの tutorial-marray の gdb ログです。

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) 

問題は一般に式テンプレートの手法に起因するものではないようです。数値を使用した配列演算は正常に機能します。ある配列を別の配列に追加しようとすると、問題が発生します。

更新。2:実際には、全体がここで言及されている問題と非常によく似ています。解決策は、演算子 E&() { return static_cast(*this); を書き直すことです。} E& get_ref() { return static_cast(*this); のようなものに const参照についても同じです。もちろん、コード内でのこれらの使用方法も変更してください。早速試して結果を報告します。

4

1 に答える 1

3

この問題は、ここで報告されているものと似ています。この問題の実際の理由は、インテル® C++ コンパイラーによって生成されたコードが次のような式を処理することです。

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

この演算子の再帰呼び出しとして。簡単な回避策は、演算子を次のようなメソッドに変更することです

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

欠点は、その演算子を使用するすべてのコード行を変更する必要があることです。幸いなことに、前述のmarrayライブラリーを使用することはそれほど難しくありませんでした。そのため、私のアプリとそのライブラリーのチュートリアルと単体テストの両方が、Intel C++ コンパイラーで魅力的に機能します。

于 2012-07-29T12:14:13.840 に答える