人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

C言語 strtok で「セグメンテーション違反」
あるC の教本で勉強しており、以下のソースをコンパイルして実行したら
「セグメンテーション違反です」エラーとなりました。
>|c|
#include <stdio.h>
#include <string.h>

int main()
{
char *ptr;

ptr = strtok("abc,def;ghi", ",;");
printf("%s\n", ptr);/* "abc" と表示する */
ptr = strtok(NULL, ",;");
printf("%s\n", ptr);/* "def" と表示する */
ptr = strtok(NULL, ",;");
printf("%s\n", ptr);/* "ghi" と表示する */

return(0);
}
||<

上を下のように修正したら、エラーなく期待どおり表示しました。
>|c|
途中省略

int main()
{
char chk[15];
strcpy( chk, "abc,def;ghi");
char *ptr;

ptr = strtok(chk, ",;");
printf("%s\n", ptr);
ptr = strtok(NULL, ",;");
printf("%s\n", ptr);
ptr = strtok(NULL, ",;");
printf("%s\n", ptr);

return(0);
}
||<
最初のコードで「セグメンテーション違反」が出た理由は何でしょうか?
それらを説明してくれているサイトなど、参考になるものを教えていただけると幸です。

OS: Vine Linux 6.2
gccバージョン: 4.4.5
よろしくお願いします。

●質問者: gdwtseq
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● Mook
●50ポイント

C でハマりやすいポインタの理解でしょうか。

下記に書かれているように、対象文字列を変更しながらポインタを返すので、
対象データとしてリテラルを使用することはできません。
C:strtok
http://www9.plala.or.jp/sgwr-t/lib/strtok.html

文字列リテラル
http://mkubara.com/index.php/%E6%96%87%E5%AD%97%E5%88%97%E3%83%AA%E3%83%86%E3%83%A9%E3%83%AB


gdwtseqさんのコメント
リテラルの参考サイトを教えていただきましてありがとうございます。 なんだか奥が深いですね。

2 ● a-kuma3
●50ポイント ベストアンサー

これが原因です。

これらの関数はその最初の引数を変更する。

Man page of STRTOK


C 言語での文字列リテラルは、コンパイラの実装に任されてはいますが、変更不能な領域に配置されることが多いです。
strtok() は、呼び出すたびに、最初の呼び出しで指定された文字列の中身を書き換えます。
質問の前半のコードでは、文字列リテラルの中身を書き換えているので、Segmentation Fault が発生します。
後半のコードでは、auto な char の配列の内容を書き換えているので、書き換えは許されており、Segmentation Fault は発生しません。

 strcpy( chk, "abc,def;ghi");
 ptr = strtok(chk, ",;");

を行うと、配列 chk に格納されている "abc" の後に続く "," が \0 に書き換えられています。
strtok() が返しているのは、実は chk の先頭アドレスです。
カンマが \0 に書き換えられているので、strtok() が返すポインタを printf で表示すると "abc" の後に続く \0 までが表示されるので、"abc" と表示されます。

同様に、次の、

 ptr = strtok(NULL, ",;");

では、"def" に続く ";" が \0 に書き換えられて、'd' が格納されている位置を strtok() が返します。


この挙動は、コンパイラによって違ってきます。
今では、ほとんど触れることはできなくなっていますが、MS-DOS の環境や、組み込み系の環境だと、文字列リテラルの内容を書き換えても、許されることがあります。


gdwtseqさんのコメント
解りやすく丁寧な説明を返していただきましてありがとうございます。 大変勉強になりました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ