旧C++Builder FAQ - ライブラリ・VCL

Abstract: この FAQは、旧 www.borland.co.jpに掲載されていた記事を転載したものです。記事は掲載時点の情報をあるがままに掲載しており、新バージョンでのご利用においては、コンポーネントや APIの仕様変更等によりご利用いただけない場合がありますのでご留意ください。

    3.0Jでコンパイル可能だった Variantタイプが 4.0Jではエラーになります(99/6/4)

該当するバージョン:C++Builder 4

Q:

3.0Jでコンパイル可能だった Variantタイプが 4.0Jではエラーになります

STDMETHODIMP TProvaImpl::Method1(TVariant* Param1)
{
  Variant v;
  *Param1 = v;  // 3.0J では問題なし
}

コンパイル後

[C++ Error] ProvaImpl.cpp(15): E2015 Ambiguity between
'TVariantT<tagVARIANT>::operator =(const TVariantT<tagVARIANT> &)' and
'TVariantT<tagVARIANT>::operator =(bool)'.

A:

4.0Jから TVariantクラスが追加されました。

C++Builderの Variantは、Delphiの Variantタイプをラップしています。

TVariant は、C++で COM/DCOMを使いやすくするために OLEの VARIANTをラップしています。

上記のエラーを回避するには TVariantでキャストするか、あらかじめ変数を TVariantで宣言しておいてください。

例1

  *Param1 = (TVariant)v;

例2

  TVariant v;
  *Param1 = v;

    DLL側で確保した変数を EXE側で解放すると例外が生成されてしまう

Q:

DLL側で確保した変数を EXE側で解放すると例外が生成されてしまいます。

どうして生成されるのでしょうか。

A:

DLL側で確保したメモリの開放を .EXE側で行うとするとアクセス権のないメモリに対して開放を実行してしまいますので例外が発生します。

この場合メモリマネージャが共有できれば問題はありません。

DLLを作成する時のプロジェクトのソースの Project1.cppに記述されているようにメモリマネージャを DLLプロジェクトとEXEプロジェクトの両方に bcbmm.libをリンクする必要があります。

    TEditのプロパティ Textの charのポインタの値が壊れます(98/12/2)

Q:

TEditの Textの charのポインタを使用してプログラムを使用していますが、ときどきその値が壊れます

  void __fastcall TForm1::Button1Click( TObject *Sender )
  {
    char buff[256];

    char *str = Edit1->Text.c_str();
    strcpy( buff, str );

    Edit2->Text = buff;  //壊れる場合があります。
  }

A:

TEditの Textはプロパティです。

プロパティはアクセスメソッドで参照されます。

Textの値を参照したとき、内部で GetText関数が呼ばれその関数が返した値が Textになります。

その返って来た値の有効期間は、Textを参照した文の終わりまでです。

つまり、上記のように charのポインタにアドレスを保存してもすぐに無効になりますので注意してください。

上記を修正したものが次のようになります。

  void __fastcall TForm1::Button1Click( TObject *Sender )
  {
    char buff[256];

    lstrcpyn( buff, Edit1->Text.c_str(), sizeof(buff));
    Edit2->Text = buff;     //正常です
  }

    TImageListの画像が正常に表示されない(Windows98) (98/11/2)

該当するバージョン:C++Builder 3

Q:

TImageListの画像が正常に表示されない(Windows98)

A:

一部のビデオカードを使用した Windows 98環境において、TImageListの画像が正常に表示されないことがあります。

この場合は、「画面のプロパティ」の「設定」ページで「詳細」ボタンを押して表示されるビデオカードの設定ダイアログの「パフォーマンス」ページで「ハードウェアアクセラレータ」の設定を「基本」または「なし」にすることで回避できる場合があります。

一般に、安全な動作環境のために、最新のドライバを利用するようにしてください。

    ForceDirectories()を使用するとリンクエラー(1998/09/04)

該当するバージョン:C++Builder 3

実行時パッケージを使用しないで構築しているアプリケーションでは、ForceDirectories()を使用するとメイク時に以下のエラーが発生する場合があります。

[リンカエラー]

Unresolved external 'Filectrl::ForceDirectories(System::AnsiString)
 __fastcall' referenced from xxxx.OBJ.

使用しているコンポーネントによってはライブラリが指定されないためリンカエラーとなります。プロジェクトにVCLX35.LIBを追加してください。

    TFormのコンストラクタを記述するとスタックオーバフローが発生する(99/6/4)

該当するバージョン:C++Builder 4

Q:

TFormのコンストラクタを、次のように記述するとスタックオーバフローが発生します。3.0Jの時は問題なく実行出来ていました。

   class TForm1 : public TForm
   {
     public:
       __fastcall TForm1( TComponent* Owner, int Dummy ):TForm(Owner){}
   };

A:

Object Pascalで記述されている TFormの標準のコンストラクタ(Create)は CreateNewを呼び出しています。

この CreateNewコンストラクタが 4.0Jから virtualに変わりました。

そのため "TForm1( TComponent* Owner, int Dummy ):TForm(Owner)"と記述されていると呼び出し順が次のようになります。

TForm1 -> TForm -> Create -> TForm1

( Pascal )

Pascalで記述された CreateNewが virtualのため、オーバーライドされた"TForm1( TComponent* Owner, int Dummy )" が Createの次に呼び出されます。

そして永久ループに入り、スタックオーバーフローが発生します。

CreateNewをオーバーライドしないように C++Builder側のコンストラクタを HIDESBASEを使って宣言して下さい。

     HIDESBASE TForm1( TComponent* Owner, int Dummy ) : TForm( Owner ){}

もしくは、C++Builder側で CreateNewを直接呼び出すように記述して下さい。

     TForm1(  TComponent* Owner, int Dummy ) : TForm( Owner, Dummy ){}