

segmentation fault 11についてです。  
変数を確認するために`printf`を入れてプログラムを書いていて発見したのですが、`printf`を使った場合このエラーが起こらないのにコメントアウトするとセグフォが起こるといった現象が起こります。

`printf`によってメモリの状況が変わるのでしょうか？

なぜ`printf`によってそのような差が生まれるのかを教えていただきたいです。


CC BY-SA 4.0
2019-12-04T16:21:19.827
61108
2019-12-05T09:37:56.530
2019-12-05T09:37:56.530
7347
36057
question
c
C言語でprintfの有り無しによってsegmentation faultになるときがある


勘違いしてはいけないのが、エラーが出ないからと言ってメモリアクセス違反がなくなった、というわけではないということです。  
C言語というのは、実行時に時間のかかるエラーチェックは省略されてまして、実行時に出るエラーというのは、たまたまその異常動作によって検出されたものが出ているだけ、と思っておきましょう。  
殆どのエラーは、エラーとしては表には出ません。

ということで、その動作は、たんにprintf命令が置かれているためにメモリ配置がビミョーに変わり、エラーとして検出されないようになっただけ、です。  
繰り返しますが、エラーが出ないといって、プログラムバグが無くなった、とはなりません。


CC BY-SA 4.0
2019-12-05T01:07:48.010
61116
2019-12-05T01:07:48.010
27481
61108
answer


`printf()` も処理の際にメモリを使います。なので `printf()` を呼ぶ場合と呼ばない場合で `printf()`
が使い終わったメモリの内容は変わります。

正しいプログラムは使い終わったメモリにアクセスしないので影響を受けないのですが  
誤ったプログラムは使い終わったメモリにアクセスして影響を受けることがあります。

おそらくあなたのプログラムは `printf()` が使い終わったメモリにアクセスしていて  
\- 呼ばない場合：メモリの値がたまたま segmentation fault になる値  
\- 呼んだ場合：メモリの値がたまたま segmentation fault にならない値  
になっているだけのことです。

  * ポインタ変数の扱いが間違っていて変なところにアクセスしているとか
  * 自動変数の初期化を忘れていて、たまたま入っている値が違うとか

が原因としてよくあります。

* * *

後者の例

[code]

    #include <stdio.h>
    void testfunc(void) {
        int uninit_auto;
        printf("%d\n", uninit_auto);
    }
    int main() {
        printf("Hello World\n"); // この行をコメントにすると挙動が変わる
        testfunc();
    }
    
[/code]

この例において `uninit_auto` は自動変数ですが、初期化していません。よって初期値は不定です。その不定値が `main()` 内部で
`printf()` するかしないかで変わります。例 `hppa2.0w-hp-hpux11.11-gcc-9.2.0` の結果

[code]

    $ gcc uninit.c # printf なしの場合
    $ ./a.out
    0
    $ gcc uninit2.c # printf ありの場合
    $ ./a.out
    Hello World
    2046468114
    $
    
[/code]

この例では `int` だからエラーが出ませんが `char* uninit_auto;` だと値によって segmentation fault
になったりならなかったりします。

# 読者の方々が自分でテストする際は、コンパイラが持っているデバッグ支援機能を無効にする必要があるかもしれない

なぜこうなるかは生成される機械語を読まないと理解できないのですがその辺は省略


CC BY-SA 4.0
2019-12-05T02:03:47.840
61119
2019-12-05T07:44:12.513
2019-12-05T07:44:12.513
8589
8589
61108
answer