アプリ版:「スタンプのみでお礼する」機能のリリースについて

MFCで、CStringをメンバとして含むクラスと、このクラスのオブジェクトを動的に生成して値を代入し、生成したオブジェクトへのポインタを返す関数を以下のように定義しました。

class Record
{
public:
 long Id;
 CString Str;
};

Record* CreateRecord(long Id_in, CString Str_in)
{
 Record* ret;
 if ((ret = (Record*)malloc(sizeof(Record))) == NULL) {
  return NULL;
 }
 ret->Id = Id_in; // (1)
 ret->Str = Str_in; // (2)
 return ret;
}

この関数のコンパイルはうまくいきますが、関数実行時にメモリ参照エラーとなります。
調べてみると、(1)のlong型変数への代入はうまくいっているのですが、(2)のCString型変数への代入がうまくいっていないようです。
既にインスタンス化されているRecord型オブジェクトへのポインタを受け取り、それに代入するという関数であればうまく動きました。
(例)
void SetRecord(Record* received, long Id_in, CString Str_in)
{
 received->Id = Id_in;
 received->Str = Str_in;
}

先に示したCreateRecord関数は、どこが良くないのでしょうか。

A 回答 (3件)

mallocでメモリを確保しただけでは、


ret->Strのコンストラクタが呼ばれていません。なので、ret->Strはめちゃくちゃな中身になっています。というわけで、ret->Strにアクセスすると落ちます。

C++で動的にメモリを使いたいときは、よっぽど特殊な事情がない限り基本的にはmallocではなくてnewを使ってください。
    • good
    • 0
この回答へのお礼

ご回答いただき、ありがとうございます。

なるほど、確かにmallocを使うと必要な量のメモリは確保されますが、実際にインスタンス化されたわけではなく、データ同士の相互関係等が未定義のままですね。
まだオブジェクト指向言語の経験が浅いので、もっと基礎を固めたいと思います。

お礼日時:2008/07/20 06:44

C++ではnewを使うというのは他の回答者さんの書かれている通り。


(あわせて、freeの代わりにdeleteを使うことも忘れずに)

その上で、現行のC++ではnewの確保失敗は単純にNULLが返るわけではありませんので、
C言語のようなNULLとの比較では意図通りに動きません。
例外処理を調べてtryを使ってください。

※コンパイラのバージョンや設定にもよります。
 例えば現行のC++仕様より古いVC6ならNULL比較で正しく動きます。
 また、MFCには独自クラスも用意されていますので、
 std::bad_allocやCMemoryExceptionをcatchします。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

C++ではメモリアロケーションエラーは例外処理を使えばいいのですね。
とても参考になります。
オブジェクトの削除もdeleteを使うようにします。

お礼日時:2008/07/20 06:50

mallocでは領域を確保したに過ぎないのではないかと思います



Record* CreateRecord(long Id_in, CString Str_in)
{
 Record* ret;
 if ((ret = new Record()) == NULL) {
  return NULL;
 }
 ret->Id = Id_in; // (1)
 ret->Str = Str_in; // (2)
 return ret;
}
といった具合に new演算子をつかってRecordクラスのコンストラクタを呼んでみましょう
    • good
    • 0
この回答へのお礼

ご回答いただき、ありがとうございます。

教えていただいたとおりnew演算子を使ってみたところ、うまく実行できました。
Cでのmallocは、C++ではnewを使えばいいのですね。

お礼日時:2008/07/20 06:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!