• ベストアンサー
  • 困ってます

newについて

newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? newした場合はdeleteをしないといけませんが、deleteした後にNULLで初期化する意味はあるのでしょうか? CとC++が混在?(newはC++かな?)しているソースなのですが、 現場(クリティカルな開発)ではこういう書き方はNGでしょうか? 組み込み系のお仕事をされている方の意見も聞きたいです。 #include <string.h> void main(void){ char *cstr = new char [3]; printf("%d\n", strlen(cstr)); // 3を期待していたのですが、7になります。 if (cstr != NULL){ delete cstr; cstr = NULL; } }

共感・応援の気持ちを伝えよう!

  • 回答数3
  • 閲覧数144
  • ありがとう数1

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

  • ベストアンサー
  • 回答No.2
  • jacta
  • ベストアンサー率26% (845/3158)

> newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? 領域は割付けても、その内容は不定だからです。 > newした場合はdeleteをしないといけませんが、 newした場合でも、常にdeleteしないといけないわけではありませんが... > deleteした後にNULLで初期化する意味はあるのでしょうか? すでにdeleteしたポインタを誤って使ってしまわないようにするための対策です。 > CとC++が混在?(newはC++かな?)しているソースなのですが、 こういうのは混在しているとはいいません。 > 現場(クリティカルな開発)ではこういう書き方はNGでしょうか? クリティカルな開発というのが何を意味するのか分かりませんが... 少なくとも、未初期化のchar配列に対してstrlenを呼び出すのはNGです。 > 組み込み系のお仕事をされている方の意見も聞きたいです。 組込み系といっても、環境がさまざまですので一概には言えません。 OSなしの環境と、μITRONのような簡易なOSの環境と、LinuxやWindowsCEのような環境では、まったく事情が異なります。

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • 多次元配列の new 2

    追加の質問ですみません^^; char の8個の配列へのポインタの配列を new する場合などは、以下のサンプルのように typedef しないとかけないんでしょうかね?たとえば、  char (**bb)[8] = new (char (*)[8])[8]; 書きたいように思いますが、これは文法違反ですし・・・^^; ==== サンプル:(iostream の初期化時に、定義した new が呼び出されるかもしれないことを一応考慮して、stdio の関数を使っています^^) #include <new> #include <stdlib.h> #include <stdio.h> void *operator new(std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new(): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete(void *p) { fprintf(stderr, "::delete(): %p\n", p); if (p) free(p); } void *operator new[](std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new[](): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete[](void *p) { fprintf(stderr, "::delete[](): %p\n", p); if (p) free(p); } int main() { typedef char (*T)[8]; char (**b)[8] = new T[8]; delete[] b; } ==== % ./a.exe ::new[](): 0x6e01b0 32 ::delete[](): 0x6e01b0

  • C++のnew演算子について質問です。

    C++のnew演算子について質問です。 以下は関数にポインタを渡して値を得ようしたプログラムです。 ※ディレクティブは省略しています。 void test( int* a ) { a = new int( 100 ); } void main() { int* b; test(b); printf( "%d", *b ); delete b; b = NULL; } このプログラムを実行すると、コンソール画面には100と表示されるかと思っていたのですが、 実際には滅茶苦茶な値と、例外が発生して強制終了しました。 また、関数に渡したポインタのアドレスもNULLとなってしまいます。 そこで以下のようにソースを変更すると正常に100が表示されました。 void test( int** a ) { *a = new int( 100 ); } void main() { int* b; test(&b); printf( "%d", *b ); delete b; b = NULL; } 結果的には目的が達成できたのでいいのですが、なぜこのような動作をするのかが いまいち釈然としません。 new演算子は自動的には破棄されないのではないのでしょうか? 回答の程、よろしくお願いします。

  • new演算子のオーバーロードについて

    #include <stdio.h> #include <windows.h> class MyNew { public: void* ptr; MyNew( void* p ) { ptr = p; } void* MyNew::operator new( size_t size ) { printf("new-\n"); return malloc( size ); } void MyNew::operator delete( void* ptr ) { printf("delete-\n"); free( ptr ); } }; void main( void ) { MyNew p = new int; } クラスのメモリ確保をnew演算子のオーバーロードを用いて書いてみたのですがオーバーロードしたnew演算子が呼ばれません。 なぜでしょうか? /** VisualStdio2005コンソールアプリケーション WindowsXP */

その他の回答 (2)

  • 回答No.3
  • zwi
  • ベストアンサー率56% (730/1282)

>newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? newしただけでは3バイトの内容は不定です。 文字列の終端は\0(0x00)ですから、\0が見つかるまでが文字列の長さということになります。たまたま、8バイト目に\0があったのでしょう。 newした文字列の領域は自分で\0を書き込むか、strcpyするときは\0を含めて3バイト以内になるように自分で面倒を見る必要があります。コンパイラは何もガードしてくれません。 >newした場合はdeleteをしないといけませんが、deleteした後にNULLで初期化する意味はあるのでしょうか? cstrをNULLにすることで領域の解法を明示的に表現します。LinuxなどでNULLにされた値を使ったらメモリ保護例外になりますし、他の環境でもcstrがNULLだったらエラーにする処理をあちこちに埋め込んでトラブルをガードする事ができます。 >CとC++が混在?(newはC++かな?)しているソースなのですが、 >現場(クリティカルな開発)ではこういう書き方はNGでしょうか? >組み込み系のお仕事をされている方の意見も聞きたいです。 CとC++の書き方を混ぜることは普通しません。読むほうもややこしくなりますから。開発の現場では、コーディング規約でどちらかに統一されているはずです。 最近質問を多くされてますが、締め切っていない質問が沢山あるみたいです。回答に不十分な部分があればお礼などで補足を求めてはどうでしょうか?満足したのなら締め切ってください。 ほとんど問い返されないので回答がうまく伝わっているのか疑問に思っています。こういう場は、お互いに情報交換しないと解決に持っていくことが難しい場合が多いですから、tobasuさんもうまく回答者コミュニケーションを取ってくださいね。 今回のnewの問題も今までの回答者の言いたいことが伝わってないんじゃないと感じました。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

わかりやすいご説明ありがとうございます。 回答を見た直後では、正直理解しておりませんが、2-3日すると少し理解できるので、しばらく申し訳ないのですが放置しています。 最終的にこの回答で解決したと断言できるのは、だいたい1週間後以降になり、それで締め切りが遅れております。 独学なので体系的に理解していなく、CとC++の過渡期の時期に、学ぶ機会を逃したので、テンプレートやstd::系の知識が0でC++を使いこなせていません。 今後もいろいろ質問させていただきますが、よろしくお願いいたします。

  • 回答No.1
  • koko_u_
  • ベストアンサー率18% (459/2509)

>printf("%d\n", strlen(cstr)); // 3を期待していたのですが、7になります。 strlen() は最初に \0 が現れるまでをカウントするので、中身の入っていない配列については、「どこまで数えられるか」予測できません。 >deleteした後にNULLで初期化する意味はあるのでしょうか? 多分、どこか別の場所で delete cstr; としたときに、領域が二重に開放されることがないように、という意図ではないでしょうか。

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • new演算子とインクリメント

    #include <iostream.h> main(){ char *str = new char[10]; memset(str, 0, 10); char *p = str; *p = 1; printf("%x", *p); delete [] str; } これで0が出力されるけど、*p = 1; を *p += 1; にすると *p += 1; の部分の実行時にエラーでフリーズしました。 この場合、*p += 1; と書いてはだめなのですか? *p = 1; との違いがあれば教えてください。

  • ポインタ勉強中です。しかも実行するとおかしいです。

    <本に載ってたソース> #include<stdio.h> #include<string.h> int main() { char msg[20]; char *str=NULL; int i; int cnt; str=&msg[0]; printf("文字を入力してください"); scanf("%s",&str); cnt=strlen(msg); str=msg+cnt; for(i=cnt;i>=0;i--){ printf("%c",*(str--)); } printf("\n"); return 0; } char *str=NULL;は、ポインタstrを空にするということでしょうか? いつもながらstrlenとsizeofが混じります。 sizeofがバイトの大きさで、strlenが、文字数でしたっけ?

  • 行が壊れました。1行の長さが2048文字を越えています。

    11行目の""の中の文字数を増やしたいのですが、そのまま増やすと「行が壊れました。1行の長さが2048文字を越えています。」といったメッセージが出てきてしまいます。 ""の中を改行するとエラーになってしまいます。 できることなら""の中を何万文字と増やしていきたいです。 実行結果が欲しいだけなのですが…。 ほとんどこういったものを使ったことがないので、簡単に解決できるのかできないのかすらわかりません。ちなみにMicrosoft Visual c++ 6.0を使用しています。 どうかよろしくお願いします。 [1] #include<stdio.h> [2] #include<string.h> [3] #include <time.h> [4] [5] [6] char *search(char *,char *); [7] [8] int main(void) [9] { [10] [11] static char text[]="あいうえお"; [12] char *p,*key="pen"; [13] [14] clock_t start,end; [15] start = clock(); [16] [17] [18] [19] p=search(text,key); [20] while (p!=NULL) [21] { [22] printf("%s\n",p); [23] p=search(p+strlen(key),key); [24] } [25] end = clock(); [26] printf("%.5f秒かかりました\n",(double)(end-start)/CLOCKS_PER_SEC); [27] return 0; [28] } [29] [30] char *search(char *text,char *key) [31] { [32] int m,n; [33] char *p; [34] [35] m=strlen(text); [36] n=strlen(key); [37] for(p=text;p<=text+m-n;p++) [38] { [39] if(strncmp(p,key,n)==0) [40] return(p); [41] } [42] return(NULL); [43] }

  • 多次元配列の new

    多次元配列を new すると、どのような型のサイズの領域の配列が確保されるんでしょうか?たとえば、  int (*a)[2] = new int[3][2]; とすると、  1. 長さ2のintの配列へのポインタ型の長さ3の配列の領域が確保される のか、  2. int[3][2] すなわち、int が 6 つ分の領域が確保される のか。 今まで、「そりゃあ 2 の方だろう」と信じ込んであまり考えずにいたんですが、「コードの型形式からすると 1 の方の解釈でもいいよなぁ」と、ふと思ったものですから、質問させていただきました。 わたしの環境で調べてみると(配列用のハウスキーピング的な余分の領域とか、パディングなどは無視して)、確かに 1 の方なんですか、これで標準準拠なんでしょうかね?^^; XP Home Edition Ver.2002 SP2 cygwin v.1.0.2-1 GNU g++ v.4.1.1 ===== #include <iostream> #include <new> #include <cstdlib> struct A { char a; void *operator new(std::size_t s) { void *p = std::malloc(s); std::cout << "A::new(): " << p << '\t' << s << '\n'; return p; } void operator delete(void *p, std::size_t s) { std::cout << "A::delete(): " << p << '\t' << s << '\n'; if (p) std::free(p); } void *operator new[](std::size_t s) { void *p = std::malloc(s); std::cout << "A::new[](): " << p << '\t' << s << '\n'; return p; } void operator delete[](void *p, std::size_t s) { std::cout << "A::delete[](): " << p << '\t' << s << '\n'; if (p) std::free(p); } }; int main() { std::cout << sizeof(char) << '\t' << sizeof(A) << '\t' << sizeof(A(*)[8]) << '\n'; A *a = new A; std::cout << a << '\n'; A *aa = new A[8]; std::cout << aa << '\n'; A (*aaa)[8] = new A[8][8]; std::cout << aaa << '\n'; A (*aaaa)[8][8] = new A[8][8][8]; std::cout << aaaa << '\n'; delete[] aaaa; delete[] aaa; delete[] aa; delete a; } ===== % ./a.exe 1 1 4 A::new(): 0x870668 1 0x870668 A::new[](): 0x870678 12 0x87067c A::new[](): 0x870688 68 0x87068c A::new[](): 0x8706d0 516 0x8706d4 A::delete[](): 0x8706d0 516 A::delete[](): 0x870688 68 A::delete[](): 0x870678 12 A::delete(): 0x870668 1

  • c++のnew演算子をオーバーロードできるものの、

    c++のnew演算子をオーバーロードできるものの、 delete演算子をオーバーロードできなくて悩んでいます。 コンパイルは通るのですが、ランタイム時に ペアとなるdeleteが呼ばれません。 inline void* operator new(size_t size, const char* filename , int line , const char* funcname ) { return my_local_malloc( size , filename , line , funcname ); } inline void operator delete(void* pMem, const char* filename , int line , const char* funcname ) { my_local_free( pMem , filename , line , funcname ); } deleteも確実にオーバーロードできる方法を ご存知のかた、お教え願います。

  • abcdとキーボードで打ったらdcbaと表示されるプログラム

    C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } }

  • メモリ開放の質問ですが

    #include<iostream> using namespace std; void main(void) { int i; char *s,*t; s=new char[9];t=s; for(i=0;i<9;i++)*(s+i)=i; for(i=0;i<9;i++)cout<<(int)s[i]<<endl; delete s; delete t; //error } において2回目のdelete tでエラーになりますが #include<iostream> using namespace std; void main(void) { int i; char *s,*t; s=new char[9];t=s+2; for(i=0;i<9;i++)*(s+i)=i; for(i=0;i<9;i++)cout<<(int)s[i]<<endl; delete t; delete s; } はエラーになりません (s=t+2をs=t+1に変更するとエラーになる) 実際にdeleteは何を行いエラーを引き起こすのでしょうか? エラーになるメカニズムを教えてください

  • プログラミング(配列と関数の引数)

    a : ABCDE a : ABCDEFGH Len : 8 a : FGHIJ a : FGH a : FGH, c : FGH 上記のように表示されるプログラムを作りたいのですが、なかなかできません。下記のようなプログラムを作ったのですがどこが間違っているのかよくわかりません。分かる方、指摘をお願いします。 #include <stdio.h> void my_strcpy(char s[], char t[]); int my_strlen(char s[]); void my_strcat(char s[], char t[]); int main(){ char a[10]; char b[10] = "ABCDE"; char c[] = "FGH"; int len; my_strcpy(a, b); printf("a : %s\n", a); my_strcat(a, c); printf("a : %s\n", a); len = my_strlen(a); printf("Len : %d\n", len); my_strcpy(a, "FGHIJ"); printf("a : %s\n", a); a[3] = '\0'; printf("a : %s\n", a); if(strcmp(a, c) == 0){ printf("a : %s, c : %s\n", a, c); } int i, s, t; my_strcpy(a, b + 2); printf("a : %s\n", a); void my_strcpy(char s[], char t[]){ for (i = 0; t[i] != '\0'; i++){ s[i] = t[i]; } s[i] = '\0'; } int my_strlen(char s[]){ int i; for (i = 0; s[i] != '\0'; i++); return i; } void my_strcat(char s[], char t[]){ int i, j; for (i = 0; s[i] != '\0'; i++); for (j = 0; t[j] != '\0'; i++, j++){ s[i] = t[j]; } s[i] = '\0'; } }

  • Vectorでヒープエラーが出る

    下記のプログラムで、2回目のループを抜けたところでヒープエラーが 出てしまいます。 2回目のループ時にv[0]とv[1]の中のbuffが同じポインタを指してしまうことが原因のようですが、なぜ同じポインタを指してしまうのかがわかりません。 どうしたらこの問題が解決するのでしょうか? 以上、よろしくお願いします。 #include "CBuff.h" main(){ vector<CBuff> v; char *tmpstr; for (int i = 0; i < 3; i++){ if (i == 0){ tmpstr = new char[5]; memcpy(tmpstr, "aaaa", 5); }else if(i == 1){ tmpstr = new char[6]; memcpy(tmpstr, "bbbbb", 6); }else { tmpstr = new char[7]; memcpy(tmpstr, "cccccc", 7); } CBuff cb; cb.setBuff(tmpstr, strlen(tmpstr) + 1); v.push_back(cb); delete [] tmpstr; } } 【CBuff.h】 #pragma once class CBuff{ char *buff; public: CBuff(); ~CBuff(); void setBuff(char*, size_t); }; CBuff::CBuff(){ buff = NULL; } CBuff::~CBuff(){ if (buff != NULL){ delete [] buff; buff = NULL; } } void CBuff::setBuff(char *input, size_t size){ buff = new char[size]; memcpy(buff, input, size); }

  • 文字列クラスを作りたいと思っています

    文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 エラーがでてしまいます。 どこかおかしいところがあるのでしょうか? *********************************************** #include<stdio.h> #include<string.h> class stt { public: char *str; int len; bool maked; stt::stt() { len=0; str=NULL; maked=false; } stt::~stt() { delete[] str; } stt &operator =(char *c) { if(maked) { delete[] str; maked=false; } len=strlen(c); str=new char[len]; strcpy(str,c); maked=true; return (*this); } virtual operator char*() { return str; } }; int main() { stt s; s="Hello World"; printf(s); getchar(); return 0; } ***********************************************