プログラムとトレースバック情報の例

この節では,トレースバックを使ってエラーの原因を特定する方法を示すサンプル・プログラムを示します。

例: ファイル終了条件 (プログラム 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

次に,このプログラムを 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 コード内の一連の呼び出しを示しています (TEOFHEREWEGOAGAIN)。

最後の 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

例: 機械語例外条件 (プログラム 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

このプログラムを 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