ポインタの初期化をしない場合にASSERT関数が正常に動作しない問題

このQ&Aのポイント
  • C++で自作のASSERT関数を作成している場合、ポインタの初期化をしないとエラーが出力されない問題が発生します。
  • ASSERT関数は、ポインタがNULLでない場合にエラーとして処理するため、ポインタをNULLで初期化する必要があります。
  • 初期化されていないポインタをASSERT関数に渡すと、条件が満たされずエラーが出力されないので、ポインタの初期化が必要です。
回答を見る
  • ベストアンサー

自作Assert関数が上手く動作しません...

開発環境:VisualStudio2013 言語:C++ Assert関数を自作してみようと思いコードを書いてみたのですが、 上手く動作してくれません。。。 お手数をおかけしますが、どなたかご指導お願いできないでしょうか? 現状:  ・char* p=NULL; ←NULLで初期化  ・ASSERT( p ); ←これは、問題なくエラー出力してくれる 問題:  ・char* p; ←初期化しない  ・ASSERT( p ); ←エラー出力してくれない。。。。 というように、ポインタにNULLが入っていないとエラー出力してくれないのです。 ソースコード template<class T> inline void ASSERT(T&p) { if ( !( p ) ) ←p がNULLで初期化していると条件文の中に入ってくれるが、 {        初期化してないと、入ってくれない・・・・ //自作ログ出力関数 OutputLogString(TEXT("Assertion Failure:%s(%d)"), __FILE__, __LINE__); } } void main(void) { char* p; ASSERT(p); } ポインタpが、NULLならもちろん、初期化されていなくてもエラーとして受け取ってくれるには、 何が足りないのでしょうか? お手数をおかけしますが、ご回答よろしくお願いします

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

  • ベストアンサー
回答No.3

逆に質問しますが、ポインタが初期化されているかされていないかを実行時に判定できると考えていますか? ASSERT(p);はpが初期化されているかどうかを判定しているのではなく、0と等しいかを判定しているんです。 未初期化のポインタは不定値になっています。 どこかの実体(char*の場合、char型の変数)のアドレスで初期化してあれば、何らかのアドレスが入っていますが、その有効なアドレスと未初期化ポインタの不定値の区別とつけることは不可能です。 char a; char*p1 = &a; // p1をaのアドレスで初期化、p1にはポインタとして有効な値は入っている char*p2; // 不定値になっているが、その値をは有効なアドレスか無効なアドレスかは不明 char*p3 = NULL; // 無効なアドレスで初期化、p3はポインタとして無効な値(0)が入っている p1, p2は0以外なのでアサートされません。 あなたの希望はp2がアサートされることですか?それは不可能です。 未初期化変数を検出するには、実行時に検出(ASSERT)するより、コンパイル時に検出する方が簡単で、コストがかかりません。VC++なら警告が出せるはずですので、わざわざASSERTでチェックするのは無駄と思います。 どうしても未初期化ポインタを実行時に見つけたい場合、スマートポインタを使用するのが有効と思われます。

whu_chan
質問者

お礼

返答が遅くなってすみません。 さっそくご回答ありがとうございます! C/C++の標準Assertでは、未初期化変数もエラー出力してくれたので、実行時に判断できる方法があるのかと考えていました。 「未初期化変数を検出するには、実行時に検出(ASSERT)するより、コンパイル時に検出する方が簡単で、コストがかかりません。VC++なら警告が出せるはずですので、わざわざASSERTでチェックするのは無駄と思います。」 この回答で納得できました。確かにコンパイル時に検出して警告を解消していくべきですね 適切なご回答ありがとうございました。もちろんベストアンサーにさせていただきます

その他の回答 (2)

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.2

#1です。もうちょっと詳しく書くと CやC++でいう変数の初期化をしていない状態というのは「値が入っていない」という状態があるわけではなく、「値は入っているが、どんな値が入っているのかは不定」という状態です。初期化をしなくても何らかの値は入っているわけですから、それを調べる事はできません。

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.1

初期化されていないという判断材料がないのでできません。

関連するQ&A

  • 自作関数で元の値を変更したい

    ポインタとかが分からないので教えてください。 元のプロセスで  case WM_KEYDOWN:   MyFunc(hWnd);   if(!hWnd)MessageBox(NULL, "成功", "", MB_OK);   else MessageBox(NULL, "エラー", "", MB_OK);  break; 元のプロセスの自作関数で void MyFunc(HWND wnd){  SetWindowText(wnd, "てすと");//これはちゃんとできた。  wnd = NULL;//ここが失敗で、この関数を抜けるまでしか効果がない。 } これで MessageBox(NULL, "エラー", "", MB_OK); が実行されてしまいました。

  • bsearch関数

    エラー 関数 `typespec' 内: 警告: 互換性のないポインタ型からの引数 5 個の `bsearch' を渡しますです int typespec(void) { static char *types[] = { "char", "int", "void" }; char *pt = token; if (bsearch(&pt, types, sizeof(types)/sizeof(char *), sizeof(char *), compare) == NULL) return NO; else return YES; } int compare(char **s, char **t) { return strcmp(*s, *t); } サイトや教科書を見たり読んだりして、標準ヘッダとも被らないように試みてみたのですが、余計エラーが増えてしまいます。「引数 5 個」ということは、全部アウトなんでしょうか? 過去の質問を見てみてもピンときません。暇な方がいるなら是非初心者にもわかりやすいアドバイスください。 (OSはLINUX。端末はGNOMEです)

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • C言語での関数の引数の受け渡しについて

    C言語での関数の引数の受け渡しについて教えてもらいたいのです。 char *p=Goo;  というポインタpがmain関数で定義され、このポインタpをある関数 void func(・・・) に渡すことは出来ますか? つまりポインタを実引数として扱うことはできるのかという事ですが・・・ int p=10; とかだったら、 void func(int test) の関数には、main関数で func(p) で仮引数testにわたせると思うんですが・・・ もし出来るようでしたら、関数の渡し方と定義の記述を教えてください。 どうか宜しくお願いします。

  • 関数へのポインタ

    超初心者です。 C言語を使ってsin波を生成して音を鳴らそうとしているのですが・・ネットで調べてもよくワカリマセン・・ 超初心者な私でも理解できるようなサイトを教えて下さい. また、関数へのポインタも勉強しているのですが, char *(*func)(void); といったchar 型へのポインタを返す関数へのポインタというのがあったとして,関数へのポインタは理解できたのですがさらにchar 型へのポインタとなると一体これが何を指しているのかさっぱりで・・・・ ご協力お願いします.

  • 再帰関数でポインタのインクリメントがうまくいかない 

    再帰関数で標準出力に文字列を表示するプログラムを書きました。 #include <stdio.h> void display(char *p); int main(void) { display("おちょめちょめ"); return 0; } void display(char *p) { if(*p){ printf("%c",*p); dis(p++); } } 実行するとbがいっぱい出てきます。?? 一番最後のコードですが、()の中を p=p+1 p+=1 p+1 などにするとちゃんと おちょめちょめ と表示されます。なぜでしょうか。

  • プログラムの動作

    独学でプログラムの勉強をしようと、サイトや本を見ながら勉強しているのですが、ポインタの使用がいまいち理解できません。 下にあるプログラムの動作の流れを順を追って教えていただきたいです。 (細かくいいますと、ポインタの動きと関数の動きの点を重点的に教えていただきたいです。(特にfor文内) 『以下プログラム』 1: #include<stdio.h> 2: 3: void h(char **p){ 4:     (*p)++; 5: } 6: 7: int main(void){ 8: 9: int i; 10: char str[]="abcdefghij"; 11: char *p_str; 12: 13: p_str=str; 14: for(i=0;i<(sizeof(str)/sizeof(str[0]));i++){ 15: printf("[%s]\n",p_str); 16: h(&p_str); 17: } 18: 19: return(0); 20: } 出力結果 [abcdefghij] [bcdefghij] [cdefghij] [defghij] [efghij] [fghij] [ghij] [hij] [ij] [j] []

  • 関数のコピー

    以下のようなソースがあります。 していることは、char配列に関数をコピーしています。それを関数ポインタに変換して、実行しています。 自作の場合はできるのですが、 MessageBoxをコピーすると以下(字数の関係上無理でした。)のようにメモリ内容がなっており、そのままコピーしたつもりですが、若干異なっております。 どのようにすればMessageBoxがじっこうできるのか, 教えていただきたく質問しました。 よろしくお願いします。 mb,code3が該当分です。 //ソース #include<stdio.h> #include<memory.h> #include<windows.h> int func(int cnt) { return cnt*10; } int func2(int cnt,int cnt2) { return cnt+cnt2; } char *func3() { return "Hello"; } int main() { int (*fa)(int); //MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaotion,UINT uType); int (*fm)(int,int); int (*mb)(HWND,LPCTSTR,LPCTSTR,UINT); char *(*hl)(void); /*fa=func; printf("%d",fa(5)); getchar(); */ char code[12800]; char code2[12800]; char code3[80000]; char code4[12800]; memset(code,0,12800); memset(code2,0,12800); memset(code3,0,80000); memset(code4,0,12800); memcpy(code,(char *)func,12800); memcpy(code2,(char *)func2,12800); memcpy(code3,(char *)MessageBox,80000); memcpy(code4,(char *)func3,12800); fa=(int(*)(int))(void *)code; fm=(int(*)(int,int))(void *)code2; mb=(int(*)(HWND,LPCTSTR,LPCTSTR,UINT))(void *)code3; hl=(char *(*)(void))(void *)code4; printf("%d\n",fa(3)); printf("%d\n",fm(3000,10)); printf(hl()); MessageBox(NULL,"","",MB_OK); mb(NULL,"","",MB_OK); getchar(); return 0; }

  • WinInetのInternetOpenUrl関数が正常に動作しない。

    ネットワーク上のHTMLソースを取得しようとしています。InternetOpenUrl関数が動作せず、常にNULLが返ってきます。 環境は、WindowsXP、WindowsCE Platform Builder です。 void Get_HTML(){ HINTERNET hInternet; HINTERNET hFile; char Buff[1000]; DWORD ReadSize; BOOL bResult; //WinInetの初期化 char *agent ="WININET Sample Program"; hInternet = InternetOpen( (LPCWSTR)agent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); if( hInternet == NULL ){ printf("InternetOpen Error \n"); } //ネット接続チェック if( InternetAttemptConnect(0) != ERROR_SUCCESS { printf("インターネットに接続できません。\n"); } else{ printf("インターネットに接続できる\n"); } //URLオープン char open_url="http://www.sample.com/sam1.html"; hFile = InternetOpenUrl( hInternet, (LPCWSTR)open_url, NULL, 0, INTERNET_FLAG_RELOAD, 0 ); printf("%s",(LPCWSTR)open_url); if( hFile == NULL ){ printf(" InternetOpenUrl ERROR \n"); } } InternetOpenUrl関数の戻り値がNULLになりReadを することが出来ません。 解決方法よろしくお願い致します。

  • ポインタ配列

    "one","two","three","four","five","six","seven","eight","nine","ten" のポインタ配列の文字列を、ASCIIコード順に並べ変えようと思ったのですが、 もうどこが間違っているかさえわからないぐらいになってしまいました。 まだまだはじめたばかりなもので、わからないことだらけなんで、 できるだけわかりやすい説明おねがいします。 関数の引数に問題があるのじゃないかと思ったのですが、 何かいいアドバイスありましたら、お願いします。 #include <stdio.h> /* 関数のプロトタイプ宣言 */ int strmp(char *,char *); void cpy(char *,char *); int main (void) { /* ポインタ配列の定義 */ char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; /* ポインタのポインタの定義 */ char **pp=x; char k[100]; char *p=k; int i,t,a,b,c,d; a=0; /* ポインタ配列を自作関数を使って、ASCIIコードの大きいほうからに並び替える */ for(i=0;i<9;i++) { for(t=1;t<10;t++) { a=strmp(*(pp+i),*(pp+t)); if(a<0) { cpy(p,*(pp+i) ); cpy(*(pp+i),*(pp+t) ); cpy(*(pp+t),p); } } } for(i=0;i<10;i++) { printf("%s ,",x[i]); } printf("\n"); return 0; } /* 文字の比較をする関数 */ int strmp(char *x,char *y) { int i; for(i=0;*(x+i)==*(y+i);i++) { if( *(x+i)=='\0') { return 0; } } return *(x+i)-*(y+i); } /* 文字をコピーする関数 */ void cpy(char *a,char *b) { int i; for(i=0;*(b+i)!='\0';i++) { *(a+i)=*(b+i); } *(a+i)='\0'; }

専門家に質問してみよう