9669


C言語で、文字列を空白で区切り、数字の配列で返す以下のような関数を書きました。しかし、この書き方だとSegmentation
faultしてしまいます。なぜでしょう?

[code]

    void putupNums(char* str, int* result) {
      char buff[80];
      int i = 0;
      strcpy(buff, strtok(str, " "));
      for(i = 0; (i < 2) && (buff != NULL); ++i) {
        result[i] = atoi(buff);
        strcpy(buff, strtok(NULL, " "));
      }
    }
    
[/code]

buffをポインタ変数にし、strtokから代入するようにすれば問題は解決するのですが、この実装でどうして動作しないのでしょうか。


CC BY-SA 3.0
2015-04-29T09:23:19.427
9663
2015-04-29T12:14:26.450
9538
question
c
strtokの返り値をstrcpyするとSegfaultするのはなぜですか


`strtok`はトークンがなくなったとき`NULL`を返します。  
Segfaultが起きるのは、`NULL`を`strcpy`でコピーしているからです。

`buff`に`strtok`の戻り値を代入した場合、`strtok`が`NULL`を返した時に`buff !=
NULL`が偽になりループを抜けるため`strcpy`は実行されません。


CC BY-SA 3.0
2015-04-29T09:40:42.570
9665
2015-04-29T09:40:42.570
3639
9663
answer


「ポインタ変数への代入」と「配列変数へのstrcpy」を混同されているようです。両者ではプログラムの意味が全く変わってしまいます。

> buffをポインタ変数にし、strtokから代入するようにすれば問題は解決する

おっしゃる通り、下記コードならば期待通り動作します。

[code]

    void putupNums(char* str, int* result) {
      char *buff;
      int i = 0;
      buff = strtok(str, " ");
      for(i = 0; (i < 2) && (buff != NULL); ++i) {
        result[i] = atoi(buff);
        buff = strtok(NULL, " ");
      }
    }
    
[/code]

ポインタ変数への代入は、`strtok`関数が返してくるポインタ値をそのまま格納します。`NULL`ポインタもそのまま格納できます。

[code]

    char *buff;
    buff = strtok(str, " ");
    
[/code]

一方の配列変数へのstrcpyでは、`strtok`関数が返したポインタが指しているデータを、文字列とみなして配列`buff`にコピーする動作になります。`NULL`ポインタが返された場合、`strcpy`関数内部では「ヌルポインタが指している文字列」にアクセスしようとして、Segmentation
faultとなります。

[code]

    char buff[80];
    strcpy(buff, strtok(str, " "));
    
[/code]


CC BY-SA 3.0
2015-04-29T12:14:26.450
9669
2015-04-29T12:14:26.450
49
9663
answer