質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

834閲覧

c言語 strcatでセグフォった原因とは

akiyama3284pga

総合スコア186

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2022/04/04 13:53

ポインタの学習中、検証のため以下のコードを実行したところ、セグフォが発生しました。
これは、一時バッファを用意せずにリテラルプールにある文字列へ上書きする結果、'\0'の分により1つずれてしまうという例を検証するためのものです。

char* string1= "abcd"; char* string2= "efgh"; strcat(string1, string2); printf("%s\n", string1); // 望む結果 => abcdefgh printf("%s\n", string2); // 望む結果 => fgh (開始アドレスのずれにより)

中間バッファを用意した場合には当然起きません。
連結もリテラルを変更しようとする動作として検知され、エラーを出しているのでしょうか。
または、教科書ではエラーは出ていないようでしたので実行環境によるものでしょうか。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/04/04 14:05

> 連結もリテラルを変更しようとする動作として検知され、エラーを出しているのでしょうか。 strcat は第1引数の文字列の後ろに第2引数の文字列を連結するという仕様ですから、"変更しようとする" しか無いと思います。
akiyama3284pga

2022/04/04 14:30

ありがとうございます。 確かにおっしゃる通りでした。 しかしなぜ教科書ではエラーになると出ていなかったのか... あまり深く考えないようにします。<(_ _)>
jimbe

2022/04/04 17:06

「セグメンテーションフォルトにならなければならない」という仕様は無いと思いますので、最終的には環境依存ではあると思います。 個々に一々「環境依存です」と注釈を入れるのもくどいと思いますので、「以下略」状態なのかもしれませんね。
thkana

2022/04/04 22:26

そもそもの話として、 > '\0'の分により1つずれてしまう という現象が一般に期待できるものではないような。 C言語のレベルでは char* string1= "abcd"; char* string2= "efgh"; がメモリ上にどう配置されるかについての縛りはないですから。 その「教科書」は、「コンパイラを作ってみよう」とかいうお題で、その特定のコンパイラの挙動の話だったりしませんか?
akiyama3284pga

2022/04/05 00:26

jimbe様 ありがとうございます。そこまで重要な雰囲気を出しているセクションではないようなので筆者もそのような意図だったのかもしれません。いずれにしてもしてはいけないことの一つとして頭に入れておきます。 thkana様 よく文章を見てみますと、"直後に配置することとする"という文脈であり、このことからもしできたとするならば的なニュアンスがありました。 確かにおっしゃる通り連続される保証はない領域の話なので、理解を促進するための一例だったのだと理解しました。ありがとうございます。ちなみにポインタの書籍です。
akiyama3284pga

2022/04/05 01:33 編集

以下のようにしますと、望む結果が得られました。 配列を用いることで、スタックにできたコピーいじるためセグフォが起きないようです。 ---------------------------------------------------------   char string1[] = "abcd"; // char string1[30] とすると当然上書きは行われない。 char string2[] = "efgh"; strcat(string1, string2); printf("%s\n", string1); // abcdefgh printf("%s\n", string2); // fgh
guest

回答2

0

そちらの環境がわからないのであてはまるかはわかりませんが、文字列リテラルはリードオンリーな .rodata セクションに割り当てられるので、そこを更新しようとしての SEGV だと思います。C 言語的には未定義動作なので動いてもいいし、コンパイルエラーや実行時エラーでもいいし、鼻から悪魔が飛び出しても OK です。

投稿2022/04/04 15:00

編集2022/04/04 15:01
68user

総合スコア2005

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

strcat(string1, string2);

string1とは、文字列定数を指しています。その文字列定数の後尾にstring2を追記する、と言う動作になるため、string1の範囲外に書き込む事となり、アクセス違反となります

投稿2022/04/04 14:01

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/04/04 14:30

ありがとうございます。 理解することができました。 本コードは使用せず、しっかりとバッファを用意して使用するよういたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問