_winmaincrtstartupはどのような機能を実行しますか?
-
21-09-2019 - |
質問
これは、少なくとも2つの密接に関連するが、明確な質問の一連の一部です。私は彼らに別々に尋ねることによって正しいことをしていることを願っています。
CランタイムライブラリなしでVisual C ++ 2008アプリを機能させようとしています。これは、MFCや他の派手なものがないWin32 GUIアプリであり、単なるWindows APIです。
したがって、プロジェクトのプロパティ - >構成 - > c/c ++ - > advanced->デフォルトのライブラリ名をyesに省略します(コンパイラフラグ /Zl
)そして再構築。
その後、リンカーは未解決の外部について不満を言います _WinMainCRTStartup
. 。十分に公平に、私はリンカーに別のエントリポイントを使用するように言うことができます、たとえば MyStartup
. 。私がウェブの周りに集めたものから、 _WinMainCRTStartup
いくつかの初期化を行います、そして私はおそらく欲しいです MyStartup
そのサブセットを行うために。
だから私の質問は次のとおりです。 機能が何をするか _WinMainCRTStartup
実行し、CRTを使用しない場合、これらのどれを省略できますか?
あなたがこのことについて知識があるなら、見てください 私の他の質問 それも。ありがとう!
さておき:そもそもなぜこれをやりたいのですか?
- 私のアプリはCRT関数を明示的に使用していません。
- 私は無駄のないアプリが好きです。
- それは私に何か新しいことを教えるでしょう。
解決
CRTのエントリポイントは次のことを行います(このリストは完全ではありません):
- CRTが必要とするグローバル状態を初期化します。これが完了していない場合、CRTが提供する機能や状態を使用することはできません。
- コンパイラが使用するいくつかのグローバル状態を初期化します。 /gsで使用されるセキュリティCookieなどのランタイムチェックは、間違いなく際立っています。あなたは電話することができます __security_init_cookie しかし、あなた自身。他の実行時間チェックに他のコードを追加する必要がある場合があります。
- C ++オブジェクトのコンストラクターを呼び出します。 C ++コードを書いている場合は、これをエミュレートする必要がある場合があります。
- コマンドラインを取得し、OSが提供する情報を起動し、メインに合格します。デフォルトでは、OSによってプログラムのエントリポイントに渡されるパラメーターはありません - それらはすべてCRTによって提供されます。
CRTソースコードはVisual Studioで利用でき、デバッガーのCRTのエントリポイントを介して、それが何をしているかを正確に確認できます。
他のヒント
a 真実 C(C ++ではない)で書かれたWin32プログラムは、初期化はまったく必要ありませんので、プロジェクトを開始できます winmaincrtstartup() それ以外の ウィンメイン(ヒンスタンス、...).
また、Consoleプログラムを真のWin32アプリケーションとして作成することも可能ですが、少し難しいです。エントリポイントのデフォルト名はです _maincrtstartup().
スタックプローブ、配列チェックなどのすべての追加のコード生成機能を無効にします。デバッグはまだ可能です。
初期化
時には最初のものが必要です ヒンスタンス パラメーター。 win32(win32sを除く)の場合、それは (Hinstance)0x400000.
ncmdshow パラメーターは常にです sw_showdefault.
必要に応じて、コマンドラインを取得します getCommandline().
終了
プログラムがスレッドを生成するとき、たとえば呼び出しによって getopenfilename(), 、から戻ってきます winmaincrtstartup() と 戻る キーワードはプログラムを掛けます - 使用します exitprocess() 代わりは。
警告
次の場合、あなたはかなりのトラブルに遭遇します
- スタックフレーム(つまり、ローカル変数)を使用する4 kbytes(関数ごと)を超える
- Float-Point Arithmetic(例:Float-> int変換)を使用する
- 32ビットマシンで64ビット整数を使用します(乗算、ビットシフト操作)
- C ++を使用します 新着, 消去, 、および非ゼロメンバーコンストラクターを持つ静的オブジェクト
- 次のような標準ライブラリ関数を使用します fopen(), printf() もちろん
トラブルシューティング
すべてのWindowsシステム(Windows95以降)で利用可能なC標準ライブラリがあります。 msvcrt.dll.
それを使用するには、エントリポイントをインポートします。 msvcrt-light.lib (Google for it)。しかし、特にMSVC6より新しいコンパイラを使用する場合、まだいくつかの注意事項があります。
- スタックフレームはまだ4つのkバイトに制限されています
- _FTOL_SSE また _FTOL2_SSE にルーティングする必要があります _ftol
- _iob_func にルーティングする必要があります _iob
その初期化はロード時に実行されるようです。少なくともファイル機能はシームレスに実行されます。
古い質問ですが、答えは間違っているか、1つの特定の問題に焦点を当てています。
プログラムが実際にMain/Winmainで開始された場合、Windows(またはほとんどのオペレーティングシステム)で使用できないC ++機能が多数あります。
この簡単な例を取ります:
class my_class
{
public:
my_class() { m_val = 5; }
int my_func(){ return m_val }
private:
int m_val;
}
my_class g_class;
int main(int argc, char **argv)
{
return g_class.my_func();
}
このプログラムが予想どおりに機能するためには、my_classのコンストラクターをMainの前に呼び出す必要があります。プログラムがメインで正確に開始された場合、メインの最初に関数呼び出しを挿入するには、コンパイラハック(注:GCCがこれを行う)が必要です(注:GCCはこれを行います)。代わりに、ほとんどのOSとほとんどの場合、異なる関数がG_CLASSを構築し、メインを呼び出します(Windowsでは、これはMainCrtstartupまたはWinmainCrtstartupです。他のほとんどのOSでは、_startと呼ばれる関数です)。
C ++およびCさえ、メインの前後に行う必要があることもあります。メインが始まるとすぐに、stdinとstdout(std :: cin and std :: cout)はどのように使用できますか? Atexitはどのように機能しますか?
C標準では、標準ライブラリにはPOSIXのような信号APIがあり、Windows上にMain()の前に「インストール」する必要があります。
ほとんどのOSでは、システムが提供するヒープはありません。 Cランタイムは独自のヒープを実装します(MicrosoftのCランタイムは、Kernel32ヒープ機能をラップするだけです)。
メインに渡された議論でさえ、ArgcとArgvは、どういうわけかシステムから得られなければなりません。
これがWindows + MSVCでどのように機能するかについての詳細については、Matt Pietrickの(古代)の記事をご覧ください(注:MingwとCygwinは特定のものを異なって実装しますが、実際にほとんどの場合MSVCRTに戻ります):http://msdn.microsoft.com/en-us/library/bb985746.aspx