2017-08-10 2 views
1

私は研究者がFortranプログラムをデバッグするのを少し助けたいと思っています。デモンストレーションの目的で、意図的にがsegfaultを引き起こすプログラムを作成しました。ここで最適化レベルが低くなるとSEGFAULTが消えますか?

はソースです:

program segfault 

    implicit none 
    integer :: n(10), i 
    integer :: ios, u 

    open(newunit=u, file='data.txt', status='old', action='read', iostat=ios) 
    if (ios /= 0) STOP "error opening file" 
    i = 0 
    do 
    i = i + 1 
    read(u, *, iostat=ios) n(i) 
    if (ios /= 0) exit 
    end do 
    close(u) 

    print*, sum(n) 

end program segfault 

data.txtファイルは100個のランダムな数字が含まれています

for i in {1..100}; do 
    echo $RANDOM >> data.txt; 
done 

私は

gfortran -O3 -o segfault.exe segfault.f90 

でこのプログラムをコンパイルするときに生成される実行可能ファイルは、律儀にクラッシュします。しかし、デバッグを有効にしてコンパイルすると:

gfortran -O0 -g -o segfault.exe segfault.f90 

次に、最初の10個の値だけが読み込まれ、合計が出力されます。価値のあるものについては、-O2は希望のsegfaultを引き起こします。-O1はそうしません。

私はこれについて深く知っています。結局のところ、デバッグシンボルを有効にしてコンパイルしたときにバグがなくなると、どうすれば正しくデバッグできますか?

誰かがこの現象を説明できますか?私はGNU Fortran (MacPorts gcc5 5.3.0_1) 5.3.0

答えて

3

セグメンテーションフォルトを使用しています

undefined behaviourです。プログラムはFortran標準に準拠していないため、特定の結果は期待できません。それはまったく何でもすることができます。あなたはセグメンテーションが起こるのを期待することはできません。

理由により利用可能なコンパイラチェック(fcheck=)とサニタイズ(-fsanitize=)があります。 segfaultを待つことは保証されません。 Fortranではなく、Cではなく、似たような言語ではありません。

不適合プログラムの結果は、メモリ内またはレジスタ内の変数の配置のような多くの要因に依存する可能性があります。メモリ内の変数の整列、スタックフレームの位置...何にも数えることはできません。これらの詳細は明らかに最適化レベルに依存します。

プログラムが範囲外の配列にアクセスするが、メモリ内のアドレスがプロセスに属しているメモリの一部である場合は、セグメンテーションが発生しないことがあります。これは、プロセスが読み書きを許可するメモリのほんの一部のバイトです(またはその両方)。他の変数を上書きしているかもしれません。古いスタックフレームからいくつかのゴミを読んでいるかもしれません。mallocの内部帳簿データを上書きして、ヒープを中断しているかもしれません。クラッシュがどこか他の場所で起こるのを待っているかもしれません。あるいは、プログラムの数値結果が多少間違っているかもしれません。何でも起れる。

関連する問題