インテル® Fortran コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

サンプルプログラムとトレースバック情報

このセクションでは、トレースバックを使用してエラーの原因を特定する方法を示すサンプルプログラムについて説明します。

これらのプログラム出力で表示される 16 進の PC とレジスターの内容は、一般的な出力の代表例です。PC は、実行ファイルの作成に使用したライブラリーとほかのツールの変更に伴って変更されます。

ファイル終了条件の例 (プログラム teof)

次の READ 文は、アプリケーションが処理しないファイル終了エラーを発生させます。

  program teof
  integer*4 i,res
  i=here( )
  end
 integer*4 function here( )
  here = we( )
  end
 integer*4 function we( )
  we = go( )
  end
 integer*4 function go( )
  go = again( )
  end
 integer*4 function again( )
  integer*4 a
  open(10,file='xxx.dat',form='unformatted',status='unknown')
  read(10) a
  again=a
  end

このプログラムをインテル® 64 アーキテクチャー・ベースのプラットフォームでトレースバックを有効にし、最適化を無効にしてビルドし、Fortran 共有ランタイム・ライブラリーとリンクすると、診断出力は次のようになります。

forrtl: 致命的なエラー (24): 読み取り中にファイルの最後に達しました。ユニット 10、ファイル E:\USERS\xxx.dat
Image            PC                Routine               Line     Source
libifcorert.dll  000007FED2B232D9  Unknown               Unknown  Unknown
libifcorert.dll  000007FED2B6CEE0  Unknown               Unknown  Unknown
teof.exe         000000013F931193  AGAIN                      17  teof.f90
teof.exe         000000013F93109B  GO                         12  teof.f90
teof.exe         000000013F931072  WE                          9  teof.f90
teof.exe         000000013F931049  HERE                        6  teof.f90
teof.exe         000000013F93101E  MAIN__                      3  teof.f90
teof.exe         000000013F96ADCE  Unknown               Unknown  Unknown
teof.exe         000000013F96B64C  Unknown               Unknown  Unknown
kernel32.dll     0000000076CC59BD  Unknown               Unknown  Unknown
ntdll.dll        0000000076EFA2E1  Unknown               Unknown  Unknown

最適化を無効 (Windows*: /Od、Linux* および macOS*: -O0) にしない場合、プロシージャーのインライン展開によりコールスタックがコラプスされ、問題を特定するのが困難です。

出力の最初の行は、標準の Fortran ランタイム・エラー・メッセージです。その後には、エラーの発生場所を特定するために、コールスタックを逆向きに巡回した結果が表示されています。個々の出力行は、スタック上の 1 つのコールフレームを表しています。アプリケーションは traceback オプションを指定してコンパイルされているため、Fortran コード内の PC は、対応するルーチン名、行番号、およびソースモジュールと関係付けられています。Fortran コード中にない PC は関係付けられずに、"Unknown" とレポートされています。

最初の 2 つのフレームは、Fortran ランタイム・ライブラリー中のルーチンへの呼び出しを (逆順で) 示しています。アプリケーションは共有ライブラリーにリンクされているため、レポートされる実行ファイルの名前は libifcore.so (Linux* および macOS*) または libifcorert.dll (Windows*) となっています。これらは、READ を実行するために、およびファイル終了 (EOF) 条件の検出時にエラーをレポートするのに呼び出されたランタイムルーチンです。未処理の I/O のプログラミング・エラーでは、コールスタック上にはこのようなランタイムコードのフレームが常にいくつか存在します。

Fortran 開発者にとって真に重要なスタックフレームは、実行ファイル teof.exe 内の最初のフレームです。ここでは、ソースモジュール teof.f90 の 17 行目の AGAIN という名前のルーチンでエラーが発生したことが示されています。ソースコードの 21 行目で、ファイル終了条件を引き起こした Fortran の READ 文があることが分かります。

次の 4 つのフレームは、エラーを発生させたルーチンに至る、Fortran コード内の一連の呼び出しを示しています (TEOF→HERE→WE→GO→AGAIN)。

最後の 4 つのフレームは、プログラムの起動と初期化を処理したルーチンです。

このプログラムが、スタティック Fortran ランタイム・ライブラリーにリンクされていた場合、出力は次のようになります。

forrtl: 致命的なエラー (24): 読み取り中にファイルの最後に達しました。ユニット 10、ファイル E:\USERS\xxx.dat
Image            PC                Routine               Line     Source
teof.exe         000000013F941FFB  Unknown               Unknown  Unknown
teof.exe         000000013F9380A0  Unknown               Unknown  Unknown
teof.exe         000000013F931193  AGAIN                      17  teof.f90
teof.exe         000000013F93109B  GO                         12  teof.f90
teof.exe         000000013F931072  WE                          9  teof.f90
teof.exe         000000013F931049  HERE                        6  teof.f90
teof.exe         000000013F93101E  MAIN__                      3  teof.f90
teof.exe         000000013F96ADCE  Unknown               Unknown  Unknown
teof.exe         000000013F96B64C  Unknown               Unknown  Unknown
kernel32.dll     0000000076CC59BD  Unknown               Unknown  Unknown
ntdll.dll        0000000076EFA2E1  Unknown               Unknown  Unknown

最初の 2 つのスタックフレームは、libifcore.so (Linux* および macOS*) または libifcorert.dll (Windows*) ではなく実行ファイル teof.exe 中のルーチンを示しています。ルーチンは共有ライブラリーの場合にレポートされた 2 つのランタイムルーチンと同じものですが、アプリケーションはアーカイブ・ライブラリー libifcore.a (Linux* および macOS*) またはスタティック Fortran ランタイム・ライブラリー libifcore.lib (Windows*) にリンクされたので、これらのルーチンを含むオブジェクト・モジュールはアプリケーション・イメージ (teof.exe) にリンクされています。「リストとマップファイルの生成」を使用して、関係付けられていない PC の場所を決定することができます。

アプリケーションがトレースバックを有効にしないでコンパイルされ、スタティック Fortran ライブラリーにリンクされた場合、診断出力は次のようになります。

forrtl: 致命的なエラー (24): 読み取り中にファイルの最後に達しました。ユニット 10、ファイル E:\USERS\xxx.dat
Image            PC                Routine               Line     Source
teof.exe         000000013F851FFB  Unknown               Unknown  Unknown
teof.exe         000000013F8480A0  Unknown               Unknown  Unknown
teof.exe         000000013F841193  Unknown               Unknown  Unknown
teof.exe         000000013F84109B  Unknown               Unknown  Unknown
teof.exe         000000013F841072  Unknown               Unknown  Unknown
teof.exe         000000013F841049  Unknown               Unknown  Unknown
teof.exe         000000013F84101E  Unknown               Unknown  Unknown
teof.exe         000000013F87ADCE  Unknown               Unknown  Unknown
teof.exe         000000013F87B64C  Unknown               Unknown  Unknown
kernel32.dll     0000000076CC59BD  Unknown               Unknown  Unknown
ntdll.dll        0000000076EFA2E1  Unknown               Unknown  Unknown

イメージに traceback によって提供された関係情報がないため、Fortran ランタイムシステムは PC をルーチン名、行番号、およびソースファイルに関係付けることができません。この場合でも、「リストとマップファイルの生成」を使用すれば、少なくともルーチン名と、それが含まれるモジュールを決定することはできます。

traceback オプションを指定してコンパイルを行うと、実行ファイルに追加の PC の関係情報が含まれるので、実行ファイルのサイズが大きくなることに注意してください。実行ファイルに追加のトレースバック情報が含まれているかどうか (.trace セクションが存在するかどうか) を調べるには、次のように入力してください。

objdump -h your_app.exe   ! Linux*
otool -l your_app.exe     ! macOS*
link -dump -summary your_app.exe   ! Windows*

traceback を指定した場合と指定しない場合でアプリケーションをビルドして、生成される実行ファイルのサイズを比較してみてください。単純なディレクトリー・コマンドでファイルのサイズを確認できます。

この teof.exe の例では、トレースバックの関係情報が含まれることで実行ファイルのサイズが 512 バイト大きくなっています。実際のアプリケーションでは、これよりもはるかに大きくなるでしょう。開発者は、個々のアプリケーションについて、実行ファイルのサイズが大きくなっても PC の関係付けを自動的に行うほうが良いのか、それとも PC とマップファイルの関係付けを手作業で行うほうが良いのかを判断しなければなりません。

コンパイル時にトレースバックを有効にした場合、エラーが発生すると、ランタイム・ライブラリーは関係情報を含むコールスタック表示を出力します。

コンパイル時にトレースバックを無効にした場合、エラーが発生すると、ランタイム・ライブラリーは関係情報を含まないコールスタック表示を出力します。

コールスタック情報を表示したくない場合、サポートされる環境変数FOR_DISABLE_STACK_TRACE を true に設定します。ただし、この場合でも次の Fortran のランタイム・エラー・メッセージは表示されます。

forrtl: 致命的なエラー (24): 読み取り中にファイルの最後に達しました。ユニット 10、ファイル E:\USERS\xxx.dat

マシン例外条件の例 (プログラム ovf)

次のプログラムは、fpe 0 を指定してコンパイルすると、浮動小数点オーバーフロー例外が生成されます。


  program ovf
  real*4 a
  a=1e37
  do i=1,10
    a=hey(a)
  end do
  print *, 'a= ', a
  end
 real*4 function hey(b)
  real*4 b
  hey = watch(b)
  end
 real*4 function watch(b)
  real*4 b
  watch = out(b)
  end
 real*4 function out(b)
  real*4 b
  out = below(b)
  end
 real*4 function below(b)
  real*4 b
  below = b*10.0e0
  end

このプログラムは、以下のオプションを指定してコンパイルされると仮定しています。

IA-32 アーキテクチャー・ベースのシステムでは、トレースバック出力は次のようになります。

forrtl: エラー (72): 浮動小数点オーバーフロー
Image              PC        Routine               Line     Source
ovf.exe            001211A3  _BELOW                     23  ovf.f90
ovf.exe            0012116F  _OUT                       19  ovf.f90
ovf.exe            0012113D  _WATCH                     15  ovf.f90
ovf.exe            0012110B  _HEY                       11  ovf.f90
ovf.exe            0012104E  _MAIN__                     5  ovf.f90
ovf.exe            0015B31F  Unknown               Unknown  Unknown
ovf.exe            0015BADD  Unknown               Unknown  Unknown
kernel32.dll       7515338A  Unknown               Unknown  Unknown
ntdll.dll          770E9902  Unknown               Unknown  Unknown
ntdll.dll          770E98D5  Unknown               Unknown  Unknown

前に示した、処理されない I/O のプログラミング・エラーの例と同様に、例外が発生した場所からスタック巡回を開始することができます。ランタイムルーチンはコールスタック上にはありません。 オーバーフローは、ソースファイル ovf.f90 の 23 行目に関係付けられている BELOW ルーチンの PC 001211A3 で発生しています。

これよりも高い最適化レベル O2fpe 0 オプションと traceback オプションを指定してプログラムをコンパイルすると、トレースバック出力は次のようになります。

forrtl: エラー (72): 浮動小数点オーバーフロー
Image              PC        Routine               Line     Source
ovf.exe            00AE1059  _MAIN__                     7  ovf.f90
ovf.exe            00B1B75F  Unknown               Unknown  Unknown
ovf.exe            00B1BADD  Unknown               Unknown  Unknown
kernel32.dll       7515338A  Unknown               Unknown  Unknown
ntdll.dll          770E9902  Unknown               Unknown  Unknown
ntdll.dll          770E98D5  Unknown               Unknown  Unknown

O2 では、プログラム全体がインライン展開されます。

メインプログラム OVF は、HEY ルーチンを呼び出さなくなっています。この出力は直観的に予想されるものとはかなり異なりますが、依然として完全に正しいものです。リリース版実行ファイルでの実行の失敗に関する診断情報を解釈するときには、コンパイラーの最適化の効果を念頭に置く必要があります。

環境変数 TBK_ENABLE_VERBOSE_STACK_TRACE を true に設定して、同じ実行ファイルをもう一度実行すると、エラーの発生時に例外コンテキスト・レコードのダンプも表示されます。IA-32 アーキテクチャー・ベースのシステムではどのように表示されるかを次に抜粋します。

forrtl: エラー (72): 浮動小数点オーバーフロー
Hex Dump Of Exception Record Context Information:
Exception Context:  Processor Control and Status Registers.
EFlags:  00010212
CS:  0000001B  EIP:  00401161  SS:   00000023  ESP:  0012FE38  EBP:  0012FE60
Exception Context:  Processor Integer Registers.
EAX: 00444488  EBX:  00000009  ECX:  00444488  EDX:  00000002
ESI: 0012FBBC  EDI:  F9A70030
Exception Context:  Processor Segment Registers.
DS:  00000023  ES:   00000023  FS:   00000038  GS:   00000000
Exception Context:  Floating Point Control and Status Registers.
ControlWord:  FFFF0262  ErrorOffset:    0040115E  DataOffset:    0012FE5C
StatusWord:   FFFFF8A8  ErrorSelector:  015D001B  DataSelector:  FFFF0023
TagWord:      FFFF3FFF  Cr0NpxState:    00000000
Exception Context:  Floating Point RegisterArea.
RegisterArea[00]:  4080BC143F4000000000  RegisterArea[10]:  F7A0FFFFFFFF77F9D860
RegisterArea[20]:  00131EF0000800060012  RegisterArea[30]:  00000012F7C002080006
RegisterArea[40]:  02080006000000000000  RegisterArea[50]:  0000000000000012F7D0
RegisterArea[60]:  00000000000000300000  RegisterArea[70]:  FBBC000000300137D9EF
...

関連情報