TOP / CODING / APP / LINK / NOTE / MAIL

※ これはATL7.0をもとに書いています

_ATL_MIN_CRTに関する話

_ATL_MIN_CRTには賛論はもちろん、批判論もあるが、私はATLを使うときは結構使っている。 ここでは使うときの落とし穴を挙げておく。参考にどうぞ。

コンソールでは使えない!?

正確には「_ATL_MIN_CRTをコンソールアプリでやってしまうとそれだけで死亡するので atl*.hヘッダがすべて使えない」というわけではない。 一部デフォルトでは使えない、というのが正しいと思う。 atlmincrt.libにはコンソールアプリ用のエントリーポイントは用意されていない(WinアプリとDLL用のはあるが)。 コンソールアプリを作ろうとすると、 見つからないもんだからリンカが自動的にCRT(libc.lib, libcmt.lib, etc)のそれをくっつけようとして、 リンクは上手くいって(CRTのスタートアップルーチンと合体)、 問題なく実行ファイルが作成される。 そのまま実行すると、main前の初期化部分でmallocを使おうとするが、 呼び出されるmalloc()はatlmincrt.lib内のものであり、 これが利用するヒープハンドルがセットされていないため (これは普通atlmincrt.libにある初期化ルーチンDoInitialization()で取得される)、落ちる。 これがsymptomとcauseの概要。 もちろん、このときにリンカオプションでCRTスタートアップコードのリンクを禁止するとリンクエラー。

最初に一部と言ったのは、落ちないときもあるからだ。例えば、AppWizardでWin32アプリを 選択して出力されたままのコンソールアプリをビルドしても、落ちない。 それは、mallocを呼ばないから。だけど例えばatlstr.hをインクルードすると落ちる。 CStringを実際に使っていなくとも。インクルードするだけでアウト。atlsimpstr.hなら問題ない。 だから回避しながらプログラムするのもあながち不可能なもんでもない。 でも面倒なことこの上ないのは確かだ。atlapp.hもダメ、すなわちWTL全滅。

さてresolution。mallocさえ呼ばなければいいのだがら、 それを一切呼ばないようなプログラムを作るか(非現実的だな)、代替mallocを自分で作るかすればよい。 でもこれではCRTのスタートアップコードがリンクされているので、単になんとか動くようにするだけ。 それなら_ATL_MIN_CRTをやめたらいい。 まともに対応するならコンソールアプリ用のエントリーポイントを自分で書いてヒープハンドルを初期化する。 提供しようかと思ったが、暇がないので保留中。いつか書こうとは思うが。 待てない人は、誰かこれを読んだ人が作ってくれるのを願ってください。

2004/03/14

書きました。WTLXの一部として配布してます。 プリコンパイルヘッダ使っている人はstdafx.cppで #include <wtlx/atlinitcexe.cpp>するのがよいでしょう。

2004/03/28

ダメだと思われてそうだけど使っても大丈夫な関数

基本的にatlmincrt.libを使うときにダメなのは、CRTのスタートアップコードが必要なもの。 よって、alloc系(atlmincrt.libに代替実装が用意されているもの以外)、浮動小数点系は使えない。 もちろん、CRTでスタティックに確保されているグローバル変数や定数も使えない。 文字列操作の多くもスタートアップコードで初期化されるテーブルを使うのでダメだ。 しかし、次の関数は大丈夫。

例外処理に関しては、C++例外処理は使えないけど、SEH(構造化例外処理)は使える。

次に挙げるいくつかの関数は/Oiコンパイルオプション、または#pragma intrinsicによって 組み込み形式(インライン)に置き換えられる。組み込み形式ならば_ATL_MIN_CRTでも問題ない。

しかし、組み込み形式を使うということは、実行ファイルのサイズが大きくなるということ。 _ATL_MIN_CRTを使う目的を損なってしまうと意味がないので、注意は払うほうがよかろう。

浮動小数点関数のいくつかも/Oiに加えて/Ogを指定することでインラインになるものがあるが、 例外処理や境界条件がもとの関数と違ってくるので、同じ関数ではなくなる。

また、一般的な使用頻度がどれくらいのものかわからないが

これらの関数は/Oiを指定しなくても常にインラインになる。

2004/03/24

CRT関数とAPIの入れ替え

いくつかのCRT関数は同様の機能を提供するAPIに置き換えることができる。 _ATL_MIN_CRT環境においてはこの入れ替えはほぼ必須。 また、_ATL_MIN_CRTを使わずともこの入れ替えだけでイメージサイズが減ることもある。 次のページに各CRT関数に対応するAPIの一覧がある。

[SDK32] C ランタイム関数の Win32 で対応する関数一覧

やはり同様の機能を提供する(公開)APIの存在しないCRT関数も多くある。 加えて、CRTのほうがAPIを使うよりも高速であることは確かだと思われる。 速度が必要なものに_ATL_MIN_CRTを使うのは少なからず熟慮が要求されるだろう。

2004/03/25


to the Top of this page