
No.5ベストアンサー
- 回答日時:
No.1の者です。
お礼欄拝見しました。まずpはこの際関係ありません。問題はあくまでもgets(s)にあります。
参考URLから引用しますが、
char *gets(char *s);
gets() は、改行文字か EOF までの 1行を stdin から読み込み s が指すバッファに格納する (末尾の改行文字や EOF は '\0' に置き換えられる)。バッファ・オーバーランのチェックは行われない (下記の バグ を参照)。
という動作をします。つまり、gets(s)を実行することによって、引数で指定したポインタ変数sが指示するメモリに書き込みが行われます。このとき、ご質問のプログラムのようにsが正しく確保されたメモリ領域をへのポインタを保持していないと、領域破壊が行われます。
sに正当に確保されたメモリへのポインタが代入されているのであれば、 p=s; または p=gets(s); とするのは、単にpもsと同じメモリ領域を指すことになるので、何も問題ありません。
なお、他の回答者も書いておられますが、C言語ではこの辺のメモリ管理についてよく理解し、プログラム内で厳密にメモリの管理を行う必要があります。そうでないと、バッファを破壊したりメモリリークを起こしたりするので注意が必要です。(他の言語のようにガベージコレクションなどは勝手にやってくれません)
No.2やNo.3の方が書いておられますが、NULLチェックを必ず行うとか、gets()のような不備のある関数は使わない、malloc()で動的に確保したメモリは確実にfree()するなどの注意が必要です。やっかいなところではありますが、Cで開発を行う以上避けて通れない道なので、これからメモリ管理を意識して勉強されるといいと思います。
参考URL:http://www.linux.or.jp/JM/html/LDP_man-pages/man …
No.7
- 回答日時:
すみません。
訂正です。誤 mfree(s)
正 free(s)
でした。
これだけではなんなので...
ググるときはたとえば malloc free メモリーリークなどとして探してください。
No.6
- 回答日時:
びーのすけと申します。
皆さんの連係プレーでいいお話が出てきたので僭越ながらワタクシもちょっと補足させていただきます。
メモリを意識するときの注意点として、メモリの確保と同じくらい(またはそれ以上に)重要なものとして、「メモリの解放」があります。
C言語はメモリの確保と解放はプログラマがきちんと目を見張らせないととんでもないことになります。
今回の場合、#1さんのプログラムを例にとらせていただきますと、
s[256]
の場合は問題はないです。
ですが、
s=malloc(256);
とした場合は、s に用が無くなったら
mfree(s);
としてシステムにメモリを帰す必要があります。
メカニズムの詳細は質問から大きく離れてしまうのでここでは割愛しますが、これを守らないと、1回や2回実行しただけでは不具合の出ない、しかも一見して見つけにくい悪魔のようなバグができてしまいます。
メモリ周りの勉強のキーワードとして、頭に留め置いてください。
No.4
- 回答日時:
がると申します。
他の方がとてもきれいに一通り説明なさっているので、簡易的補足をちょろりと。
C言語は、物凄く「メモリを意識する必要がある」言語です。
そのために、基本的にすべての「データを入れる変数の領域の確保」を意識する必要があります。
特にchar *とかの場合において非常に重要で初心者のかたが分からなくなりがちなので。
そういった「メモリ周り」とかをきちんと学ぶか、教わるか、するとよろしいかと思われます。
No.3
- 回答日時:
余談ですが、gets()は入力の制限ができない大変危険な関数なので、安全に使えるfgets()をお勧めします。
#include <stdio.h>
int main()
{
char *p;
char s[200];
p = fgets(s, sizeof(s), stdin);
if (p != NULL) {
printf("%s", s);
}
return 0;
}
fgetsってこういう関数だったんですね。
勉強になりました。ありがとうございます。
これからは極力こっちを使うようにしたいです。
No.2
- 回答日時:
#1の方がお答えになっているように、領域を確保することで解決しますが、ついでに気になったことを…
printf("%s" , p);
とされていますが、getsで入力がなかった場合には p がNULLになってしまいます。
getsの使い方としては、sのバッファに入力データを格納する。
pは正しく入力されたかどうかを確認するために使用するのが良いと思います。
p = gets(s)
if (p != NULL)
{
printf("%s" , s);
}
return 0;
No.1
- 回答日時:
このソースでは、sはポインタとして宣言されているだけで、実際にgetsで取得した文字列を格納するメモリ領域が確保されてません。
char *p,s[256];
のように配列として宣言するか、
char *p,*s;
s=malloc(256);
のように動的にメモリ領域を確保する必要があります。
なるほど。最初に領域が決まっていないので領域破壊が起こるということですね。
ところで以下のプログラムはちゃんと動くのですが、これの場合
p = gets(s);
を
gets(s);
p = s;
と書き換えただけです。
getsの戻り値がchar *型なのでそれがsに代入されてさらにその値をpに代入しているわけですが、
p = gets(s);とするのだってpにchar *型の戻り値を代入しているだけなのに何故領域が破壊されるのか分かりません。
両者の違いとは何なのでしょうか?
p = sなどとしたときは p に s 分の領域が確保されるのでしょうか?
#include <stdio.h>
int main ( void ){
char *p, *s;
gets(s);
p = s;
printf("%s", p);
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ヒープメモリの解放について
-
allocってなんですか?
-
newしないオブジェクトについて
-
アセンブラでのメモリの動的確...
-
mallocでメモリーを確保しよう...
-
変数に文字列を代入する方法を...
-
領域の確保について
-
C言語で作ったゲームがフリーズ...
-
テキストファイルを二次元配列に
-
c言語のポインタへの文字列入力...
-
配列の中身のdelete
-
なぜ動かないのかわからないです。
-
指定したメモリアドレスの値の...
-
C++で、メンバもヒープに確保さ...
-
C++のnewで確保したメモリーの...
-
こんな画面構成にしたいのですが
-
new と malloc によるメモリの...
-
構造体でchar name[]と*nameの...
-
malloc でのメモリ取得状況の可...
-
stringの最大サイズ
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
allocってなんですか?
-
newしないオブジェクトについて
-
malloc呼び出し時のセグメンテ...
-
入れ子になった構造体について
-
ヒープメモリの解放について
-
ビットをローテートするプログ...
-
C++で、メンバもヒープに確保さ...
-
void*型のデータサイズ
-
Win32APIでのメモリ管理について
-
配列の添え字の最大数とは?
-
C++のnewで確保したメモリーの...
-
プログラムが途中で強制終了し...
-
C言語 mallocとfreeについて
-
win32APIのHeapAlloc()の使い方...
-
LoadLibraryでAccess Violation...
-
グローバル変数のサイズ
-
MFCのCStringについて
-
メモリ不足になってしまう。
-
ヒープの実際の限界値は?
おすすめ情報