C言語の初学者です。
コンパイラは、Borland C++ 5.5.1 for Win32 を使っています。
たまたま見つけた C magazine プログラミングの禁じ手Web版 C言語編で、「NULL領域を読み書きする」という個所があり、下記ソースで発覚すると掲載されていました。
(http://www.cmagazine.jp/src/kinjite/c/null.html# …
void f()
{
static char *theTxt;
strcpy(theTxt,"TEST\n");
printf("%s",theTxt);
}
自分の環境で、下記のソースで動かしてみたところ、アプリケーションエラーになりました。
#include <stdio.h>
#include <string.h>
int main(void)
{
static char *theTxt; /* (1) */
strcpy(theTxt,"TEST\n");
printf("%s",theTxt);
return 0;
}
この禁じ手の意味そのものが、全く理解できませんでした。
・NULL領域というのは、(1)のstatic定義されたポインタことをさしているのか?
・(1)の static をつけないで実行すると、正常終了したので、static の領域に書き込んではいけないのか?
(そんなことはないと思うのだが)
No.2ベストアンサー
- 回答日時:
NULL領域というのは、NULLポインタで示された領域ということかと
思われます。NULLポインタは値としては0をとることが一般的ですが、
定義としては「どこも指さないポインタ」です。
ですから、NULLポインタへのアクセスは、仮に動作したとしても適切な
処理ではなく、行なってはいけません。
http://www.st.rim.or.jp/~phinloda/cqa/cqa3.html
例題ですが、明示的に初期化していないstatic宣言された変数は0(数値型)
またはNULL(ポインタ型)に初期化されますので、theTxtはNULLポインタ
です。それを strcpy(theTxt,"TEST\n"); でアクセスしていますので
適切な処理ではないということになります。
>NULL領域というのは、(1)のstatic定義されたポインタことをさしているのか?
static宣言されていなくても、theTxt=NULL; のようにポインタにNULLが
代入されていれば同様です。
>(1)の static をつけないで実行すると、正常終了したので...
static宣言されていない局所変数は不定ですので、その値は環境によって
変わります。ですからいつも同じ動作となる保証はなく、不定のポインタに
アクセスすることも行なってはいけません。
NULLポインタや不定のポインタ、不定の数値を処理してしまうことは
ありがちで、C言語のバグのもとになっているケースが
多くみられます。
最近のコンパイラでは、警告レベルを高くしておくと、コンパイルの時点で
これらについて警告(Warning)を出すものもあり、注意すると実行前に
気づく場合もありますので、Warningにも注意した方がいいかと思います。
参考URL:http://www.st.rim.or.jp/~phinloda/cqa/cqa3.html
丁寧に答えていただきありがとうございました。
今まで、アドレスを考慮しないで済むプログラミングの世界におりましたので、この回答で理解することができました。
No.1
- 回答日時:
>NULL領域というのは、(1)のstatic定義されたポインタことをさしているのか?
「NULL領域」という言葉を聞いたことはありませんが、
たぶんメモリの0番地のことを言っているんでしょう。
「アプリケーションがアクセスしてもいいメモリ領域はここからここまで」
と決まっている(たぶん)から、0番地は触ってはいけない
ということだと思います。
static で定義された変数は、明示的に初期化をしなければ
勝手に0に初期化されます。
ですから、
static char *theTxt;
とすると、theTxtの値は0になります。
つまり theTxt は0番地を指しているわけです。
そこに
strcpy(theTxt,"TEST\n");
によって "TEST\n" を書き込もうとしたから、
「そんなとこ触っちゃイヤ」
というエラーが出たのでしょう。
>(1)の static をつけないで実行すると、正常終了したので、...
static をつけないと、初期値としてテキトーな入ります。
正常終了したのは、たまたま触ってもいい領域の値が
theTxtに入っていたからではないでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
アプリを32bitから64bit移行
-
DLL<->VB間での受け渡し(文字...
-
C言語のポインタに直接アドレス...
-
LPSTR型の初期化について
-
参照型で受け取った引数をポイ...
-
戻り値で構造体を返すことは可...
-
構造体とfscanf
-
fopne で失敗する原因
-
NASMかNASKの文法の本
-
関数ポインタの高速化のメリット
-
自作関数の引数
-
Cで作成したDLL関数をVBから呼...
-
popenした子プロセスのプロセス...
-
#define NULL ((void *)0) の弊害
-
C言語のプログラムをJavaに...
-
visual studioのエラーについて
-
x64プログラムでアドレスが32bi...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
C言語の関数と配列に関する質問
-
Run-Time Check Failure #3とい...
-
LPSTR型の初期化について
-
ExcelVBAでのkernel32(64bit)
-
main(int argc,char **argv[])...
-
アプリを32bitから64bit移行
-
ハンドルはポインタか
-
連結リスト 要素の入れ替え
-
C言語でのconstを返す関数
-
Cで作成したDLL関数をVBから呼...
-
NULLとブランクの違い
-
エラーの意味
-
ハンドル、アドレス、ポインタ...
-
DLL<->VB間での受け渡し(文字...
-
【C言語】戻り値が構造体の関数
おすすめ情報