VCでコンパイル、実行プログラムの豆知識ポイント


1、Run-Time Library
Run-ime Libraryはコンパイラが提供する標準ライブラリであり、基本的なライブラリ関数とシステム呼び出しを提供します。
私たちが一般的に使うRun-Time LibraryはC Run-Time Libriesです。もちろんStandard C++libriesもあります。
C Run-Time LibriesはANSI Cの標準ライブラリを実現します。VCのインストールディレクトリのCRTディレクトリには、C Run-Timeライブラリのソースコードの大部分があります。
C Run-Time Libriesはスタティックライブラリバージョンがあり、ダイナミックリンクライブラリバージョンもあります。シングルスレッドバージョンもあり、マルチスレッドバージョンもあります。デバッグとデバッグ以外のバージョンもあります。
「project」-「settings」-「C/C+」-「Code Generation」でRun-Time Libraryのバージョンを選択することができます。
ダイナミックリンクライブラリバージョン:
/MD Multihreaded DLL導入ライブラリMSVCRT.LIBを使用する
/MDd Debug Multihreaded DLL導入ライブラリMSVCRTD.LIBを使用する
スタティックライブラリのバージョン:
/ML Single-ThreadedスタティックライブラリLIBC.LIBを使用する
//MLd Debug Single-ThreadedスタティックライブラリLIBCD.LIBを使用する
/MT MultihreadedスタティックライブラリLIBMT.LIBを使用する
/MTd Debug MultihreadedスタティックライブラリLIBMTD.LIBを使用する
C Run-ime Libraryの標準io部分はオペレーティングシステムと密接な関係があります。WindowsではCRTのio部分コードは一つの包装にすぎません。オペレーティングシステムのカーネルケネル32.dllの関数を使って、コンパイルする時にクーカーネル32.libを導入します。つまり、組み込み環境の中では、C標準ライブラリを直接使用することはできません。
Linux環境にはもちろんC標準ライブラリもあります。例えば:
ld-o output/lib/crt 0.o hello.o-lc
パラメータ「-lc」はC標準ライブラリlibc.aを参照しています。「-lm」はどのライブラリのファイルを参照しますか?
2、共通のコンパイルパラメータ
VCのプロジェクトを設立する時、いつも“Win 32”を定義します。コンソールプログラムの定義CONSOSE「そうでないと定義されます。」WINDOWS"。Debug版定義“_”DEBUG「Release版定義」NDEBUG「
MFC DLLに関するコンパイル定数は、以下を含む。
_。WINDLLはMFCを使うDLLをすると言いました。
_。USRDLLは、1つのユーザDLLを行うことを表す(MFC拡張DLLに対して)。
_。AFXDLLはMFC動的リンクライブラリを使用することを表している。
_。AXEXTはMFC拡張DLLをすると表しています。
だから:
Reglar,statically linked to MFC_WINDLL,_USRDLL
Reglar,using the shared MFC DLL_WINDLL,_USRDLL、_AXDLL
Extension DLLWINDLL,_AFXDLL,_AXEXT
CL.EXEは全てのソースファイルをコンパイルし、LIK.EXEはEXEとDLLをリンクし、LIB.EXEは静的なライブラリを生成します。
3、subsystemと実行可能ファイルの起動
LINKの場合は指定/subsystemが必要ですが、このリンクオプションはWindowsに実行可能ファイルの実行方法を教えます。
コンソールプログラムは/subsystem:「consolie」です。
その他のプログラムは普通すべて/subsystem:「windows」です。
subsystemを「consone」に選択すると、Windowsは実行可能ファイルのコードに入る前に、コンソールウィンドウを作成します。
「windows」を選択すると、オペレーティングシステムはconsoneウィンドウを生成しません。このタイプのアプリケーションのウィンドウはユーザー自身で作成します。
実行可能ファイルはいずれもEntry Pointがあります。LINKでは/entryで指定できます。デフォルトの場合、subsystemが「consolite」であれば、Entry PointはmanCRTStatup(ANSI)またはwmanCRTStatuup(UNCODE)である。
//subsystem:「consone」/entry:「manCRTStatup」(ANSI)
//subsystem:「consone」/entry:「wmann CRTStatuup」(UNCODE)
manCRTStatupまたはwmanCRTStatuupは、mainまたはwmainを呼び出します。
なお、WindowsのローダはアプリケーションのEntry Pointに入る前にすでにC変数の初期化をしています。初期値のあるグローバル変数はそれらの初期値を持ち、初期値のない変数は0に設定されています。
subsystemが「windows」であれば、Entry PointはWinMain(ANSI)またはwWinMain(UICODE)である。
//subsystem:「windows」/entry:「WinMainCRTStatup」(ANSI)
//sbusystem:「windows」/entry:「wWinMainCRTStatup」(UICODE)
WinMainCRTStatupまたはwWinMainCRTStatupはWinMainまたはwWin Mainを呼び出します。
これらのエントリポイント関数は、CRTディレクトリでソースコードを見ることができます。
void mainCRTStartup(void)
{
        int mainret;

        /* Get the full Win32 version */
        _osver = GetVersion();
        _winminor = (_osver >> 8) & 0x00FF ;
        _winmajor = _osver & 0x00FF ;
        _winver = (_winmajor << 8) + _winminor;
        _osver = (_osver >> 16) & 0x00FFFF ;

#ifdef _MT
        if ( !_heap_init(1) )               /* initialize heap */
#else  /* _MT */
        if ( !_heap_init(0) )               /* initialize heap */
#endif  /* _MT */
            fast_error_exit(_RT_HEAPINIT);  /* write message and die */

#ifdef _MT
        if( !_mtinit() )                    /* initialize multi-thread */
            fast_error_exit(_RT_THREAD);    /* write message and die */
#endif  /* _MT */

        __try {
            _ioinit();                      /* initialize lowio */
            _acmdln = (char *)GetCommandLineA();        /* get cmd line info */
            _aenvptr = (char *)__crtGetEnvironmentStringsA();        /* get environ info */
            _setargv();
            _setenvp();
            __initenv = _environ;
            mainret = main(__argc, __argv, _environ);
            exit(mainret);
        }
        __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
        {
            _exit( GetExceptionCode() );        /* Should never reach here */
        } /* end of try - except */
}  
MFCフレームを使用すれば、WinMainもMFCライブラリに埋め込まれる(APPMODUL.C):
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
ANSIバージョンについては、“_”twinMainは「Win Main」です。UICODEバージョンについてはtwin Mainは「wWin Main」です。afx.hを参照できます
#ifdef _UNICODE
#define _tmain wmain
#define _tWinMain wWinMain
#else
#define _tmain main
#define _tWinMain WinMain
#endif
グローバルC++オブジェクトの構造関数はどこで呼び出しますか?答えは、アプリケーションのEntry Pointに進んだ後、main関数を呼び出す前の初期化動作です。だからMFCのtheAppの構造関数は_にあります。twinMainの前に呼び出しました。
4、Consolieウィンドウを表示しないCosolieプログラム
デフォルトでは/subsystemと/entryスイッチが一致します。
「consolie」は「manCRTStatup」または「wmanCRTStatup」に対応しています。
「windows」は「WinMain」または「wWin Main」に対応します。
私たちは手動で修正した方法で彼らを不整合にすることができます。たとえば:
#include "windows.h"
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) //       
void main(void)
{
MessageBox(NULL, "hello", "Notice", MB_OK);
}
このConsoneプログラムはコンサートウィンドウが表示されません。MLdを選択すると、このプログラムはLIBCD.LIB user 32.libケネル32.libのみをリンクする必要があります。
実はConsoneウィンドウを見たくないなら、もっと直接的な方法があります。それはEXEファイルで直接PEファイルのヘッダをSubsystemを3から2に変えます。EXEファイルでは、PEファイルヘッダのオフセットアドレスは0 x 3 cであり、SubsystemはWORDであり、PEファイルヘッダのオフセットは0 x 5 cである。
5、MFCのライブラリファイル
MFCのライブラリは静的にリンクすることができ、動的にリンクすることもできる。スタティックライブラリとダイナミックライブラリには、DebugとRelease、ANSIとUnicoodeのバージョンがあります。
静的MFCライブラリは主にあります。
ANSI Debug NAFXWD.LIB
ANSI Release NAFXCW.LIB
Unicode Debug UAFXCWD.LIB
Unicode Release UAFXCW.LIB
ダイナミックリンクライブラリは主にあります。
ANSI Debug MFCxD.LIB(core,MFCxD.DLL)は、
MFCOxD.LIB(OLIE,MFCOxD.DLL)は、
MFCDxxxx D.LIB(database、MFCDxD.DLL)は、
MFCNxD.LIB(network,MFCNxD.DLL)は、
MFCSxxD.LIB(static)
ANSI Release MFCxx.LIB(combined、MFCxx.DLL)
MFCSxx.LIB(static)
Unicode Debug MFCxUD.LIB(core,MFCxUD.DLL)は、
MFCOxUD.LIB(OPE,MFCOxUD.DLL)、
MFCDxxUD.LIB(database、MFCDxUD.DLL)は、
MFCNxUD.LIB(network,MFCNxUD.DLL)は、
MFCSxUD.LIB(static)
Unicoode Release MFCxU.DLL(commbined、MFCxU.DLL)は、
MFCSxU.LIB(static)
上のLIBファイルはMFCSxx(D、U、UD)、LIB以外はインポートライブラリです。
MFCダイナミックリンクライブラリバージョンもいくつかのファイルを静的にリンクする必要があります。これらのファイルはMFCSxx(D、U、UD).LIBに配置されます。例えば_を含むtwinMainのappmodul.cpp。
6、おわりに
これらの問題を研究する動機は、私たちのプログラムがどのようにロードされ、実行されているかを明らかにしたいからです。しかし、Windowsはオープンソースプラットフォームではないので、PEファイル(Windowsで実行可能ファイルのフォーマット)を研究するしかないです。entry point、subsystemはすべてPEファイルヘッダの一部です。
WindowsはPEファイルのentry pointに入る前に何をしましたか?見えなくなりました。大体の推測しかできません。PEファイルと必要なDLLをロードして、C変数を初期化して、ある起点関数から実行を開始します。subsystemとは違って、出発点が違うはずです。この起点関数を呼び出すときは、PEファイルのentry pointアドレスに入るべきです。
転載住所:これを押してください。