この節では,トレースバックを使ってエラーの原因を特定する方法を示すサンプル・プログラムを示します。
次の例の 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
次に,このプログラムを ia32 プラットフォームでトレースバックを有効にしてビルドし,シングルスレッド DLL Fortran 実行時ライブラリーとリンクしたときに表示される診断出力を示します。
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat Image PC Routine Line Source DFORRT.dll 1000A3B2 Unknown Unknown Unknown DFORRT.dll 1000A184 Unknown Unknown Unknown DFORRT.dll 10009324 Unknown Unknown Unknown DFORRT.dll 10009596 Unknown Unknown Unknown DFORRT.dll 10024193 Unknown Unknown Unknown teof.exe 004011A9 AGAIN 21 teof.for teof.exe 004010DD GO 15 teof.for teof.exe 004010A7 WE 11 teof.for teof.exe 00401071 HERE 7 teof.for teof.exe 00401035 TEOF 3 teof.for teof.exe 004013D9 Unknown Unknown Unknown teof.exe 004012DF Unknown Unknown Unknown KERNEL32.dll 77F1B304 Unknown Unknown Unknown
出力の最初の行は,標準 Fortran 実行時エラー・メッセージです。その後には,エラーの発生場所を特定するために,コール・スタックを逆向きに巡回した結果が表示されています。個々の出力行は,スタック上の 1 つのコール・フレームを表しています。アプリケーションは /traceback を指定してコンパイルされているので,Fortran コード内の PC は,対応するルーチン名,行番号,およびソース・モジュールと関係付けられています。Fortran コード中にない PC は関係付けられておらず,"Unknown" と報告されています。
最初の 5 つのフレームは,Fortran 実行時ライブラリー中のルーチンへの呼び出しを示しています。アプリケーションはシングルスレッド DLL 版のライブラリーにリンクされているので,報告される実行形式ファイル名は DFORRT.dll となっています。これらは,READ を実行するために,ファイル終了 (EOF) 条件の検出時にエラーを報告するために呼び出された実行時ルーチンです。未処理の I/O のプログラミング・エラーでは,コール・スタック上にはこのような実行時コードのフレームがつねにいくつか存在します。
Fortran 開発者にとって真に重要なスタック・フレームは,実行形式ファイル teof.exe 内の最初のフレームです。ここでは,エラーが AGAIN という名前のルーチンの teof.for ソース・モジュールの 21 行目で発生したことが示されています。ソース・コードの 21 行目を見ると,ファイル終了条件を引き起こした Fortran の READ 文があることがわかります。
次の 4 つのフレームは,エラーを発生させたルーチンに至る,Fortran コード内の一連の呼び出しを示しています (TEOF→HERE→WE→GO→AGAIN)。
最後の 3 つのフレームは,プログラムの起動と初期化を処理したルーチンです。
このプログラムがシングルスレッド・スタティック Fortran 実行時ライブラリーにリンクされていた場合,出力は次のようになります。
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat Image PC Routine Line Source teof.exe 004067D2 Unknown Unknown Unknown teof.exe 0040659F Unknown Unknown Unknown teof.exe 00405754 Unknown Unknown Unknown teof.exe 004059C5 Unknown Unknown Unknown teof.exe 00403543 Unknown Unknown Unknown teof.exe 004011A9 AGAIN 21 teof.for teof.exe 004010DD GO 15 teof.for teof.exe 004010A7 WE 11 teof.for teof.exe 00401071 HERE 7 teof.for teof.exe 00401035 TEOF 3 teof.for teof.exe 004202F9 Unknown Unknown Unknown teof.exe 00416063 Unknown Unknown Unknown KERNEL32.dll 77F1B304 Unknown Unknown Unknown
最初の 5 つのスタック・フレームは,DFORRT.DLL ではなく実行形式ファイル teof.exe 中のルーチンを示しています。ルーチンは DLL の場合で報告された 5 つの実行時ルーチンと同じものですが,アプリケーションは Fortran スタティック実行時ライブラリー (dfor.lib) リンクされたので,これらのルーチンを含んでいるオブジェクト・モジュールは実行形式ファイル (teof.exe) 中にリンクされています。マップ・ファイルから,一番上のスタック・フレーム 004067D2 に報告されている PC が,ライブラリー dfor.lib のモジュール for_diags.obj 内の _for_stack_trace ルーチン中にあることがわかります (004067a0 < PC=004067D2 < 004079f0)。
... 0001:000057a0 _for_stack_trace 004067a0 f dfor:for_diags.obj 0001:000069f0 _for__find_trace_info_file 004079f0 f dfor:for_diags.obj ...
アプリケーションがトレースバックを有効にせずにコンパイルされ,シングルスレッド・スタティック Fortran 実行時ライブラリーにリンクされたとすると,診断出力は次のようになります。
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat Image PC Routine Line Source teof.exe 00406792 Unknown Unknown Unknown teof.exe 0040655F Unknown Unknown Unknown teof.exe 00405714 Unknown Unknown Unknown teof.exe 00405985 Unknown Unknown Unknown teof.exe 00403503 Unknown Unknown Unknown teof.exe 00401169 Unknown Unknown Unknown teof.exe 004010A8 Unknown Unknown Unknown teof.exe 00401078 Unknown Unknown Unknown teof.exe 00401048 Unknown Unknown Unknown teof.exe 0040102F Unknown Unknown Unknown teof.exe 004202B9 Unknown Unknown Unknown teof.exe 00416023 Unknown Unknown Unknown KERNEL32.dll 77F1B304 Unknown Unknown Unknown
/traceback が提供していた関係情報がないため,Fortran 実行時システムは PC をルーチン名,行番号,およびソース・ファイルに関係付けることができません。この場合でも,マップ・ファイルを使えば,少なくともルーチン名と,それが含まれているモジュールを決定することはできます。この実行形式のマップ・ファイルのエントリ・ポイント一覧の先頭は次のようになっています。
Address Publics by Value Rva+Base Lib:Object 0001:00000000 _TEOF 00401000 f teof.obj 0001:00000000 _TEOF@0 00401000 f teof.obj 0001:00000000 _MAIN__ 00401000 f teof.obj 0001:0000003d _HERE 0040103d f teof.obj 0001:0000003d _HERE@0 0040103d f teof.obj 0001:0000006d _WE@0 0040106d f teof.obj 0001:0000006d _WE 0040106d f teof.obj 0001:0000009d _GO 0040109d f teof.obj 0001:0000009d _GO@0 0040109d f teof.obj 0001:000000cd _AGAIN 004010cd f teof.obj 0001:000000cd _AGAIN@0 004010cd f teof.obj 0001:00000180 _for_rtl_init_ 00401180 f dfor:for_init.obj ...
最初の 5 つのスタック・フレームは実行時のコード中にあり (これは,マップ・ファイルのここには示していない部分からわかります),6 番目のフレームは 00401169 という PC を示しています。マップ・ファイル上に示した部分からは,この PC が 004010cd よりも大きく,00401180 よりも小さいので,コール・スタック上の最初の Fortran ルーチンである _AGAIN ルーチンに含まれていることがわかります。残りの PC は,呼び出し列を再構築するのと同じような方法で,手作業で関係付けることができます。
/traceback を指定してコンパイルを行うと,実行形式ファイルに余分な PC の関係情報が含まれることになるので,実行形式ファイルの大きさが増えることに注意してください。実行形式ファイルに余分なトレースバック情報が含まれているかどうか (.trace セクションが存在するかどうか) を調べるには,次のように入力してください。
link -dump -summary your_app.exe
teof.exe の例では,次のように表示されます。
Microsoft ® COFF Binary File Dumper Version x.xx.xxxx Copyright (C) Microsoft Corp 1992-1998. All rights reserved. Dump of file teof.exe File Type: EXECUTABLE IMAGE Summary 1000 .data 1000 .idata 1000 .rdata 1000 .text 1000 .trace
単純なディレクトリ・コマンドでファイルの大きさを確認してみてください。次に,トレースバック付きで Fortran ダイナミック実行時ライブラリーにリンクされた teof.exe の例を示します。
03/03/98 01:45p 5,120 teof.exe 1 個のファイル 5,120 バイト
トレースバックなしの場合,次のようになります。
03/03/98 01:46p 4,608 teof.exe 1 個のファイル 4,608 バイト
この簡単な例では,トレースバックの関係情報は実行形式ファイルの大きさを 512 バイト増やしています。実際のアプリケーションでは,これよりもはるかに大きくなるでしょう。開発者は,個々のアプリケーションについて,自動的な PC の関係付けが実行形式ファイルの大きさを増加することに引き合うのか,それとも PC とマップ・ファイルの関係の手作業での調査が許容可能なのかどうかを判断しなくてはなりません。
コマンド行を使用する場合と,ビジュアル開発環境の「Release」構成では,トレース情報は基本設定では Fortran のコンパイルには含まれません (基本設定は /notraceback です)。ビジュアル開発環境の「Debug」構成では,基本設定は /traceback です。「Release」構成では,「Project Settings」ダイアログボックスの「Fortran」タブの「Run Time」カテゴリでトレースバックを要求することができます。
コンパイル時にトレースバックを要求した場合,エラーが発生すると,実行時ライブラリーは関係情報を含んだコール・スタック表示を出力します。
コンパイル時にトレースバックを無効にした場合,エラーが発生すると,実行時ライブラリーは関係情報を含まないコール・スタック表示を出力します。
コール・スタック情報を表示したくない場合,環境変数 FOR_DISABLE_STACK_TRACE を真に設定します。ただし,この場合でも次の Fortran の実行時エラー・メッセージは表示されます。
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat
次のプログラムは,/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
このプログラムを ia32 システムで /traceback,/fpe:0 および /optimize:0 を指定してコンパイルすると,トレースバック出力は次のようになります。
forrtl: error (72): floating overflow Image PC Routine Line Source ovf.exe 00401161 BELOW 29 ovf.f90 ovf.exe 0040113C OUT 24 ovf.f90 ovf.exe 0040111B WATCH 19 ovf.f90 ovf.exe 004010FA HEY 14 ovf.f90 ovf.exe 0040105B OVF 7 ovf.f90 ovf.exe 00432429 Unknown Unknown Unknown ovf.exe 00426C74 Unknown Unknown Unknown KERNEL32.dll 77F1B9EA Unknown Unknown Unknown
前に示した,処理されない I/O のプログラミング・エラーの例と同様に,例外の起こった場所からスタック巡回を開始することができます。実行時ルーチンはコール・スタック上にはありません。オーバーフローは BELOW ルーチン中の PC 00401161 で起こっており,ソース・ファイル ovf.for の 29 行目に関係付けられています。
プログラムをこれよりも高い最適化レベル /optimize:4 で /traceback と /fpe:0 を指定してコンパイルすると,トレースバック出力は次のようになります。
forrtl: error (72): floating overflow Image PC Routine Line Source ovf.exe 00401070 OVF 29 ovf.f90 ovf.exe 004323E9 Unknown Unknown Unknown ovf.exe 00426C34 Unknown Unknown Unknown KERNEL32.dll 77F1B9EA Unknown Unknown Unknown
/optimize:4 では,プログラム全体がインライン展開されます。これはリスト・ファイルを見れば簡単に確認できます。
... .CODE PUBLIC _MAIN__ 0000 _MAIN__ PROC 55 0000 push ebp EC8B 0001 mov ebp, esp 30EC83 0003 sub esp, 48 000000E8 0006 call _for_check_flawed_pentium@0 00 04EC83 000B sub esp, 4 0020058D 000E lea eax, dword ptr .literal$+32 0000 50 0014 push eax 000000E8 0015 call _for_set_fpe_@4 00 001C058D 001A lea eax, dword ptr .literal$+28 0000 50 0020 push eax 000000E8 0021 call _for_set_reentrancy@4 00 04C483 0026 add esp, 4 001805D9 0029 fld dword ptr .literal$+24 ; 000029 0000 00000DD8 002F fmul dword ptr .literal$ 0000 9B 0035 fwait 00000DD8 0036 fmul dword ptr .literal$ 0000 9B 003C fwait 00000DD8 003D fmul dword ptr .literal$ 0000 9B 0043 fwait 00000DD8 0044 fmul dword ptr .literal$ 0000 9B 004A fwait 00000DD8 004B fmul dword ptr .literal$ 0000 9B 0051 fwait 00000DD8 0052 fmul dword ptr .literal$ 0000 9B 0058 fwait 00000DD8 0059 fmul dword ptr .literal$ 0000 9B 005F fwait 00000DD8 0060 fmul dword ptr .literal$ 0000 9B 0066 fwait 00000DD8 0067 fmul dword ptr .literal$ 0000 FC5DD9 006D fstp dword ptr -4[ebp] 9B 0070 fwait D233 0071 xor edx, edx ; 000009 0014058D 0073 lea eax, dword ptr .literal$+20 0000 03D045C7 0079 mov dword ptr -48[ebp], 3 000000 D44589 0080 mov dword ptr -44[ebp], eax 000C0D8D 0083 lea ecx, dword ptr .literal$+12 0000 DC458D 0089 lea eax, .T1_ ; eax, dword ptr -36[ebp] DC5589 008C mov .T1_, edx ; dword ptr -36[ebp], edx 04EC83 008F sub esp, 4 D0558D 0092 lea edx, dword ptr -48[ebp] 52 0095 push edx 51 0096 push ecx 84FF0068 0097 push 126156544 07 FFFFFF68 009C push -1 FF 50 00A1 push eax 000000E8 00A2 call _for_write_seq_lis 00 18C483 00A7 add esp, 24 FC458B 00AA mov eax, dword ptr -4[ebp] D04589 00AD mov dword ptr -48[ebp], eax 04EC83 00B0 sub esp, 4 D0558D 00B3 lea edx, dword ptr -48[ebp] 00040D8D 00B6 lea ecx, dword ptr .literal$+4 0000 DC458D 00BC lea eax, .T1_ ; eax, dword ptr -36[ebp] 52 00BF push edx 51 00C0 push ecx 50 00C1 push eax 000000E8 00C2 call _for_write_seq_lis_xmit 00 10C483 00C7 add esp, 16 E58B 00CA mov esp, ebp ; 000010 000001B8 00CC mov eax, 1 00 5D 00D1 pop ebp C3 00D2 ret _MAIN__ ENDP ...
主プログラム OVF は,HEY ルーチンを呼び出さなくなっています。この出力は直観的に予想されるものとはかなり異なりますが,依然として完全に正しいものです。リリース版実行形式ファイルでの実行の失敗に関する診断情報を解釈するときには,コンパイラ最適化の効果を念頭に置く必要があります。
環境変数 FOR_ENABLE_VERBOSE_STACK_TRACE を真に設定して,同じ実行形式ファイルをもう一度実行すると,エラーの発生時に例外文脈記録のダンプが表示されます。次に ia32 システムで表示されるものの抜粋を示します。
forrtl: error (72): floating overflow 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 ...
例: Fortran と C が混在したアプリケーションでのトレースバックの使用 (プログラム FPING および CPONG)
次の例では,Fortran と C が混在したアプリケーションでトレースバック出力を使用する方法を示します。主プログラムは FPING という名前の Fortran プログラムです。プログラム FPING は,一連の関数呼び出し中で,Fortran と C のコードを交互に呼び出します。やがて,Unlucky という名前の C のルーチンが呼び出され,ゼロによる除算の浮動小数点エラーが発生します。
ソース・モジュール FPING.FOR には,それぞれソース・モジュール CPONG.C の C ルーチンを呼び出す Fortran 関数定義が含まれています。FPING.FOR は /fpe:0 /optimize:0 /traceback のオプションを有効にして ia32 プラットフォームでコンパイルされます。次に,プログラムのトレースバック出力を示します。
forrtl: error (73): floating divide by zero Image PC Routine Line Source fping.exe 00401161 Unknown Unknown Unknown fping.exe 004010DC DOWN4 58 fping.for fping.exe 0040118F Unknown Unknown Unknown fping.exe 004010B6 DOWN3 44 fping.for fping.exe 00401181 Unknown Unknown Unknown fping.exe 00401094 DOWN2 31 fping.for fping.exe 00401173 Unknown Unknown Unknown fping.exe 00401072 DOWN1 18 fping.for fping.exe 0040104B FPING 5 fping.for fping.exe 004013B9 Unknown Unknown Unknown fping.exe 004012AF Unknown Unknown Unknown KERNEL32.dll 77F1B304 Unknown Unknown Unknown
Fortran ルーチンに対応するスタック・フレームは,ルーチン名,行番号,およびソース・モジュールと関係付けられていますが,C ルーチンに対応するフレームは関係付けができないことに注目してください。スタックを逆向きに巡回し,PC を報告することはできても,PC をルーチン名や行番号などに関係付けるのに必要な情報は,Fortran コンパイラが生成したオブジェクトの実行形式ファイルから得られます。C コンパイラにはこの機能はありません。また,Fortran のコンパイルの際にも,/traceback オプションを指定しないと,関係情報は得られないということに注意してください。
一番上のスタック・フレームは,C コードに含まれているので,ルーチン名に関係付けることはできません。アプリケーションのマップ・ファイルを見ると,報告された PC である 00401161 がルーチン _Unlucky の始点よりも大きく,ルーチン _down1_C の始点よりも小さいことがわかるので,このエラーが少なくとも _Unlucky ルーチンの中で起きたことがわかります。次にマップ・ファイル内の該当するセクションを示します。
Address Publics by Value Rva+Base Lib:Object 0001:00000000 _FPING 00401000 f fping.obj 0001:00000000 _FPING@0 00401000 f fping.obj 0001:00000000 _MAIN__ 00401000 f fping.obj 0001:0000005f _DOWN1 0040105f f fping.obj 0001:0000005f _DOWN1@4 0040105f f fping.obj 0001:00000083 _DOWN2@4 00401083 f fping.obj 0001:00000083 _DOWN2 00401083 f fping.obj 0001:000000a5 _DOWN3 004010a5 f fping.obj 0001:000000a5 _DOWN3@4 004010a5 f fping.obj 0001:000000c7 _DOWN4@4 004010c7 f fping.obj 0001:000000c7 _DOWN4 004010c7 f fping.obj 0001:00000100 _Fact 00401100 f cpong.obj 0001:00000127 _Pythagoras 00401127 f cpong.obj ****************************************************** The reported PC lies between the start of _Unlucky and the start of _down1_C... ****************************************************** 0001:0000014d _Unlucky 0040114d f cpong.obj 0001:00000167 _down1_C 00401167 f cpong.obj 0001:00000175 _down2_C 00401175 f cpong.obj 0001:00000183 _down3_C 00401183 f cpong.obj 0001:00000192 _for_check_flawed_pentium@0 00401192 f dfordll:DFORRT.dll 0001:00000198 _for_set_fpe_@4 00401198 f dfordll:DFORRT.dll 0001:0000019e _for_set_reentrancy@4 0040119e f dfordll:DFORRT.dll etc...
同じように,"Unknown" として報告された他の PC も,マップ・ファイルを使ってルーチン名に関係付けることができます。
トレースバック出力 (また,その意味ではあらゆる形式の診断出力) を調べるときには,コンパイラ最適化の影響を考慮に入れることが重要です。上の例の Fortran ソース・モジュールは,最適化をオフにして,すなわち /optimize:0 でビルドされていました。次に,最適化を有効にして,/optimize:4 を指定したときの出力を示します。
forrtl: error (73): floating divide by zero Image PC Routine Line Source fping.exe 00401111 Unknown Unknown Unknown fping.exe 0040109D DOWN4 58 fping.for fping.exe 0040113F Unknown Unknown Unknown fping.exe 00401082 DOWN3 44 fping.for fping.exe 00401131 Unknown Unknown Unknown fping.exe 0040106B DOWN2 31 fping.for fping.exe 00401123 Unknown Unknown Unknown fping.exe 00401032 FPING 18 fping.for fping.exe 00401369 Unknown Unknown Unknown fping.exe 0040125F Unknown Unknown Unknown KERNEL32.dll 77F1B304 Unknown Unknown Unknown
トレースバック出力からは,ルーチン DOWN1 が一度も呼び出されなかったように見えます。実際,このルーチンは呼び出されていません。高度な最適化レベルでは,コンパイラは関数 DOWN1 をインライン展開するので,FPING からはルーチン down1_C への呼び出しが行われるようになっています。関係付けられた行番号は,依然としてソース・コード内の正しい行を指しています。FPING.LST リスト・ファイルを見ると,DOWN1 がインライン展開されていることがわかります。
.CODE PUBLIC _MAIN__ 0000 _MAIN__ PROC 55 0000 push ebp EC8B 0001 mov ebp, esp 04EC83 0003 sub esp, 4 53 0006 push ebx 000000E8 0007 call _for_check_flawed_pentium@0 00 04EC83 000C sub esp, 4 0008058D 000F lea eax, dword ptr .literal$+8 0002 50 0015 push eax 000000E8 0016 call _for_set_fpe_@4 00 0004058D 001B lea eax, dword ptr .literal$+4 0002 50 0021 push eax 000000E8 0022 call _for_set_reentrancy@4 00 000035FF 0027 push dword ptr .literal$ ; 000018 0000 000035FF 0027 push dword ptr .literal$ ; 000018 0000 ******************************************************************* Call _down1_C from MAIN__ here, no call to DOWN1 Fortran routine... ******************************************************************* 000000E8 002D call _down1_C 00 C0DD 0032 ffree st(0) F7D9 0034 fincstp 08C483 0036 add esp, 8 000001B8 0039 mov eax, 1 ; 000006 A0 5B 003E pop ebx E58B 003F mov esp, ebp 5D 0041 pop ebp C3 0042 ret _MAIN__ ENDP
最後に,例の Fortran コードの設計を変更し,個々の Fortran ルーチンを独立したソース・モジュールに分割したとします。再設計したコードのトレースバック出力は次のようになります。
forrtl: error (73): floating divide by zero Image PC Routine Line Source fpingmain.exe 00401171 Unknown Unknown Unknown fpingmain.exe 004010ED DOWN4 12 fping4.for fpingmain.exe 0040119F Unknown Unknown Unknown fpingmain.exe 004010C1 DOWN3 11 fping3.for fpingmain.exe 00401191 Unknown Unknown Unknown fpingmain.exe 00401099 DOWN2 11 fping2.for fpingmain.exe 00401183 Unknown Unknown Unknown fpingmain.exe 00401073 DOWN1 11 fping1.for fpingmain.exe 0040104B FPING 5 fpingmain.for fpingmain.exe 004013C9 Unknown Unknown Unknown fpingmain.exe 004012BF Unknown Unknown Unknown KERNEL32.dll 77F1B304 Unknown Unknown Unknown
コードの新しい設計を反映して,行番号とソース・ファイルの関係情報が変わっていることに注意してください。
次に,上の例で使用したソースを示します。
!************************************ ! FPING.FOR !************************************ program fping real*4 a,b a=-10.0 b=down1(a) end real*4 function down1(b) real*4 b !DEC$ IF DEFINED(_M_X86_) INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'_down1_C'] (n) !DEC$ ELSE INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'down1_C'] (n) !DEC$ ENDIF REAL*4 n [VALUE] END real*4 down1_C down1 = down1_C(b) end real*4 function down2(b) real*4 b [VALUE] !DEC$ IF DEFINED(_M_X86_) INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'_down2_C'] (n) !DEC$ ELSE INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'down2_C'] (n) !DEC$ ENDIF REAL*4 n [VALUE] END real*4 down2_C down2 = down2_C(b) end real*4 function down3(b) real*4 b [VALUE] !DEC$ IF DEFINED(_M_X86_) INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'_down3_C'] (n) !DEC$ ELSE INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'down3_C'] (n) !DEC$ ENDIF REAL*4 n [VALUE] END real*4 down3_C down3 = down3_C(b) end real*4 function down4(b) real*4 b [VALUE] !DEC$ IF DEFINED(_M_X86_) INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'_Unlucky'] (a,c) !DEC$ ELSE INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'Unlucky'] (a,c) !DEC$ ENDIF REAL*4 a [VALUE] REAL*4 c [REFERENCE] END real*4 a call Unlucky(b,a) down4 = a end
/************************************/ /* CPONG.C */ /************************************/ #include <math.h> extern float __stdcall DOWN2 (float n); extern float __stdcall DOWN3 (float n); extern float __stdcall DOWN4 (float n); int Fact( int n ) { if (n > 1) return( n * Fact( n - 1 )); return 1; } void Pythagoras( float a, float b, float *c) { *c = sqrt( a * a + b * b ); } void Unlucky( float a, float *c) { float b=0.0; *c = a/b; } float down1_C( float a ) { return( DOWN2( a )); } float down2_C( float a ) { return( DOWN3( a )); } float down3_C( float a ) { return( DOWN4( a )); }
!************************************ ! FPINGMAIN.FOR !************************************ program fping real*4 a,b a=-10.0 b=down1(a) end
!************************************ ! FPING1.FOR !************************************ real*4 function down1(b) real*4 b !DEC$ IF DEFINED(_M_X86_) INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'_down1_C'] (n) !DEC$ ELSE INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'down1_C'] (n) !DEC$ ENDIF REAL*4 n [VALUE] END real*4 down1_C down1 = down1_C(b) end
!************************************ ! FPING2.FOR !************************************ real*4 function down2(b) real*4 b [VALUE] !DEC$ IF DEFINED(_M_X86_) INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'_down2_C'] (n) !DEC$ ELSE INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'down2_C'] (n) !DEC$ ENDIF REAL*4 n [VALUE] END real*4 down2_C down2 = down2_C(b) end
!************************************ ! FPING3.FOR !************************************ real*4 function down3(b) real*4 b [VALUE] !DEC$ IF DEFINED(_M_X86_) INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'_down3_C'] (n) !DEC$ ELSE INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'down3_C'] (n) !DEC$ ENDIF REAL*4 n [VALUE] END real*4 down3_C down3 = down3_C(b) end
!************************************ ! FPING4.FOR !************************************ real*4 function down4(b) real*4 b [VALUE] !DEC$ IF DEFINED(_M_X86_) INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'_Unlucky'] (a,c) !DEC$ ELSE INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'Unlucky'] (a,c) !DEC$ ENDIF REAL*4 a [VALUE] REAL*4 c [REFERENCE] END real*4 a call Unlucky(b,a) down4 = a end