• ベストアンサー

NULL領域を読み書きするの意味が?

C言語の初学者です。 コンパイラは、Borland C++ 5.5.1 for Win32 を使っています。 たまたま見つけた C magazine プログラミングの禁じ手Web版 C言語編で、「NULL領域を読み書きする」という個所があり、下記ソースで発覚すると掲載されていました。 (http://www.cmagazine.jp/src/kinjite/c/null.html#index5) 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 の領域に書き込んではいけないのか? (そんなことはないと思うのだが)

質問者が選んだベストアンサー

  • ベストアンサー
  • ara_ara
  • ベストアンサー率35% (124/348)
回答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
yasunosuke
質問者

お礼

丁寧に答えていただきありがとうございました。 今まで、アドレスを考慮しないで済むプログラミングの世界におりましたので、この回答で理解することができました。

その他の回答 (1)

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答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に入っていたからではないでしょうか。

yasunosuke
質問者

お礼

0番地に書き込もうとしたからですね。 やっと意味が理解できました。 ありがとうございました。

関連するQ&A

  • 領域の開放がされているかどうかはどうやって調べればいいのでしょう。

    #include <stdio.h> #include <stdlib.h> int main(void){ char *str; printf("&str : %d\n", &str); // ●領域割り当て前のアドレス(NULL) printf("str : %d\n", str); str = (char *)calloc(15, sizeof(char)); // (1)領域割り当て後のアドレス printf("str : %d\n", str); // str領域開放 free(str); // (2)領域解放後のアドレス printf("str : %d\n", str); return 1; } 開放した後は●と同じくNULLになると思っていたのですが、 実際に実験してみて(1)と(2)のアドレスが同じものでした。 アドレスは割り当てたままに見えますが、実際にはちゃんと開放されているのでしょうか? それとも、何か間違えているでしょうか。 よろしくお願いします。

  • C言語のNULLについて

    C言語のNULLについて教えてください。 ・NULLは、アドレスの0番地であり、参照先が無い(どこのメモリ箇所も指していない)と  言う認識でいます。 そこで、仮に下記の処理を行った場合どうなるか試してみました。 ------------------------------------------ stddef.h (void *)0) ------------------------------------------ char *test; test = NULL; printf("[%p]\n", test); // 出力 [00000000] printf("[%s]\n", test); // 出力 [] memcpy(test, "123", 3); // メモリフォルト ------------------------------------------ 予想としては、%sの処理でメモリフォルトとなると思っていたのですが 実際は、メモリフォルトが起こらなかったです。 と言う事は参照先が何かしらあったって事なのでしょうか?

  • Expression: nptr != NULL

    デバックではエラーが出なかったのですが、プログラムを走らせた所タイトルのような line:68 Expression: nptr != NULL のエラーが出ました。何が悪いのか分かりません。よろしければ、ご教示お願いします。 68行目もどこか書いておきました。 #include<stdio.h> #include<math.h> #include<string.h> #include <stdlib.h> #include <string.h> #include <windows.h> #include "conio.h" FILE *input; char fname[30]; int keisan(void); int main(void){ char *ret,infname[60],csv[]=".csv"; loop: printf("読み込むファイル名を入力してください\n"); scanf("%s",&fname); ret=strstr(fname,csv); if(ret!=NULL){printf("拡張子[.csv]を入力しないでください\n");goto loop;} strcpy(infname,fname); strcat(infname,csv); input=fopen(infname,"r"); if(input==NULL){ printf( "%sファイルが開けません\n",infname); return -1; }else{ keisan(); } fclose(input); return 0; } int keisan(void){ FILE *output; char outfname[60]; char str[256]; char *n,*nouse; int k=0; double n1,n2,time=60,times; int start=2; int line=0; strcpy(outfname,fname); strcat(outfname,"1.csv");//出力ファイル形式 output=fopen(outfname,"w"); while(fgets(str,256,input)!=NULL){ line++; if(line>=start){ k++; times=(double)k/time; n=strtok(str, ",");//1行目 n=strtok(NULL,",");//2行目 n1=strtod(n,&nouse); n=strtok(NULL,",");//3行目 n=strtok(NULL,",");//4行目 n2=strtod(n,&nouse);   ←←←68行目 printf("%d,%lf,%2.2lf,%2.1lf \n",k,times,n1,n2); fprintf(output,"%d,%lf,%2.2lf,%2.1lf \n",k,times,n1,n2); } } fclose(output); return 0; }

  • 参照渡しにならないのは何故?

    参照渡しにならないのは何故? 基本的な質問で大変恐縮なのですが、C言語で以下のコードを書いてみました。 メインの関数ではchar型のポインタのみ用意し、呼び出し先のtest関数内で当該ポインタ用に 領域を割り当て文字列をコピーしています。 ここまでは良いのですが、呼び出し元のメイン関数に戻るとtest関数にて設定したはずの値 が消えてしまいます。 結局のところ、メインの関数で用意したchar型のポインタがうまくtest関数にわたっていない (?)ような動作なのですが、どうしてこうなってしまうのか理解できず苦しんでいます。 ご教授いただければ幸いです。 #include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *pc_buf){ pc_buf = (char *)malloc(10); memset(pc_buf,(int)NULL,10); strcpy(pc_buf,"12345"); return; } void main(){ char *pc_buf; pc_buf = NULL; test(pc_buf); printf("[%s]\n",pc_buf);getchar(); }

  • ptrcpy関数 コピーする領域の確保について

    prcrpyを使い、コピーする領域の確保をわざと少なめにしたプログラムを 下のようにかいたのですが、エラーが出ません。 どうしてでしょうか? #include <stdio.h> #include <string.h> main() { char s[5] = "Hello"; printf("%s\n",s); strcpy(s,"Good bye") ; printf("%s\n",s); }

  • 多元配列について(ANSI C)

    動的多元配列で、 Voidポインタに、多種の型がぶら下がった多元配列を作り、 読み書きをしたいのですがどのようにしたらよろしいでしょうか。 具体的には、 x[0][1]は、intで「2」が入っている x[0][4]は、intで「9」が入っている x[1][2]は、charでしかも文字列の配列で「goo」が入っている x[1][5]は、charでしかも文字列の配列で「教えて」が入っている x[0]は、int型の配列。X[1]は、文字列型の配列。 というようなものです。 一応ソースは作ってみたのですが、int型では問題なくいくのですが、 文字列は、コンパイルはできますが、実行すると予期せぬことが起きます。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main (void) {      void **topPointa;      int * iDataInput;      int * iDataOutput ;      char * chDataInput;      char * chDataInput2;      char * chDataOutput1 ;      // ポインタアドレス用のメモリ確保      topPointa = (void *) calloc (10 , sizeof(void *));      if(topPointa == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      //int配列のメモリ確保      iDataInput = (int * ) calloc (10 , sizeof(int));      if(iDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      iDataInput[0] = 3 ;      iDataInput[1] = 4 ;      topPointa[0] = (void * ) &iDataInput;      //int配列の取り出し      iDataOutput = *(int *) topPointa[0];      printf( "int: %d\n", iDataOutput[0] );      printf( "int: %d\n", iDataOutput[1] );      //char配列 のメモリ確保      chDataInput = (char * ) calloc (10 , sizeof(char *));      if(chDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      chDataInput2 = (char * ) calloc (10 , sizeof(char));      if(chDataInput2 == NULL) {           printf("メモリが確保できません\n");           exit(-1);       }      strcpy(chDataInput2 , "hoe");      chDataInput[0] = &chDataInput2;      topPointa[1] = (void * ) &chDataInput;      //char配列の取り出し      chDataOutput1 = *(char *) topPointa[1];      printf( "char: %S\n", chDataOutput1[0] );      free(iDataInput);      free(chDataInput);      free(chDataInput2);      return 0; } 言語は、C言語ANCI Cでお願いします。 以上。よろしくお願いします。

  • 文字列のコピー

    C言語で、文字列をコピーする関数で、処理が止まってしまいます。 以下が実行したプログラムです。 #include<stdio.h> #include<string.h> void copy(char *str2 ,char *str3){ strcpy(str2,str3); } void input(char* str){ scanf("%s",str); } int main (void){ char *a; char *b="TEST"; printf("%s\n",b); input(a); copy(b,a); printf("%s",b); return(0);} copy(b,a);で処理が止まってしまいます。入力した文字列を表示できるように、御指摘お願いします。

  • srand(time(NULL))の使い方

    C言語の勉強中で「ランダムな整数値を作成し、その数値が偶数か奇数かを判定するプログラムをif~else 構文を使って作成」したいのですが下記のプログラムでやってみたのですがまだまだ知識不足で完成しません。知識をお借りできればと思っていますのでどなたか教えてください。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void) { { int = i; i = rand(); srand((unsigned)time(NULL)); printf("%d\n",rand()); } if(i % 2 == 0) { printf("偶数である:\n",i); } else { printf("奇数である:\n",i); } return 0; }

  • dlopenで目的の*.soファイルをロードできません

    以下C++のテストソース2ファイルをコンパイルし実行したのですが、libtest.soをロードすることが出来ません。OSはRed Hat Linux EL4.0WS、カーネルは2.6.9-5です。原因と思しき点がお分かりの方がいれば、教えて頂けますでしょうか。 ********** ソースファイル1(libtest.cpp) ********** #include <stdio.h> #include <stdlib.h> extern "C" {void printTest();} void printTest(){ printf(" *** SUCCESS!! *** Java - Native Interface test at INOAC\n"); } ********** ソースファイル2(test.cpp) ********** #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> static void (*testFunc)(); int main(){ void *library; const char * error; library = dlopen("libtest.so",RTLD_LAZY); if(library==NULL){ printf("Could not open libtest.so\n"); exit(1); } dlerror(); testFunc = (void (*)())dlsym(library,"printTest"); error = dlerror(); if(error){ printf("Could not find the function printTest\n"); exit(1); } printf("Test from C;\n"); (*testFunc)(); dlclose(library); return 0; } ********** 実行方法 ********** pgCC -fPIC -shared libtest.cpp -o libtest.so pgCC -ldl test.cpp -o test.exe setenv LD_LIBRARY_PATH "." ./test.exe

  • C言語の変数について

    C言語の変数について教えていただきたいです。 C言語で下記のような設定をした場合、変数A、Bに設定する値にはバイト数制限 はないのでしょうか? バイト数制限がなくなる場合、なぜそうなるのかを教えていただきたいです。 よろしくお願いします。 #include <stdio.h> void test( char **B); int main( int argc, char *argv[] ) { char *A = NULL; char *B = NULL; A = argv[1]; test( B ); return 0; } void test( char **B ) { strcpy(B, "ABCD"); return 0; }

専門家に質問してみよう