SDK Index Previous page Next page

実行ファイルサイズを減らす


窓プログラムをしていて どうして窓の実行ファイルはこんなにでかいんだ と思ったことはないでしょうか? ここでは、そんな悩みを制限付きですがかなえてみます。

まずは、その制限から

 1.シングルスレッドプログラムである。

 2.API以外は使わないほうがいい。使うとかなりサイズが増える。(stdio.hもだめ!)

 3.VC++でしかできない(BC++での方法もあるけど少し難しい)

この3つです。
まあ、1つ目の制限については、マルチスレッドプログラムはそう作らないと思うので殆ど問題はないと思います。
ただ、2つ目に関しては、DOS時代からCを使ってる人にはつらいかもしれません。 しかし、Cで出来たことはほとんどどAPIで出来るので、APIの勉強だと思って下さい。ただ、memcpyなどはAPIにない(CopyMemoryっていうのがあるが、あれは実はmemcpyを呼んでる)ので使わざるをえないですが、あまりサイズが増えないので大丈夫だと思います。99/07/19 補足
問題は、3つ目です、これはどうしようもないですね。BC++での方法もだいたい分かっているのですが、 今、僕はVC++を使ってるのではっきりとしたことが分かりません。わかり次第掲載するのでしばらく待って下さい。

あと、VC++6ではファイルのアライメントが変わってしまったので、以前のバージョンよりも大きなファイルになってしまいます。それがいやだというときには、リンクオプションに/opt:nowin98をつけると以前と同じサイズになります

では、具体的な方法を示します

<VC++編 EXEファイル用>

まず、次のプログラムを打ち込んで、コンパイルしてobjファイルを作って下さい。 リンクは必要ありません。
void __cdecl WinMainCRTStartup( void )

{
    int mainret;
    char *lpszCommandLine;
    STARTUPINFO StartupInfo;

    lpszCommandLine = GetCommandLine();

    if ( *lpszCommandLine == '"' )  // Check for and handle quoted program name
    {
        do{
            lpszCommandLine++;
        }while( *lpszCommandLine && (*lpszCommandLine != '"') );

        if ( *lpszCommandLine == '"' )
            lpszCommandLine++;
    }
    else    // First token wasn't a quote
    {
        while ( *lpszCommandLine > ' ' )
            lpszCommandLine++;
    }

    while ( *lpszCommandLine && (*lpszCommandLine <= ' ') )
        lpszCommandLine++;

    StartupInfo.dwFlags = 0;
    GetStartupInfo( &StartupInfo );

    mainret = WinMain( GetModuleHandle(NULL),
                       NULL,
                       lpszCommandLine,
                       StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                            ? StartupInfo.wShowWindow : SW_SHOWDEFAULT );

    ExitProcess(mainret);
}
objファイルが出来たら、今度はダイエットしたいプログラムのソースのあるディレクトリにコピーしたあとで、そのプログラムのワークスペースを開いて下さい。
開いたら、プロジェクト−設定を選び、その中のリンクを選んで下さい。
そのなかに、オブジェクト/ライブラリ モジュール(L)というところがあるので、その先頭にさっきのobjファイルの名前を書きます。このとき、設定の対象をReleaseにしてください。

tiny01

これで終わりです。 後はコンパイルして、普段より小さな実行ファイルが出来れば成功です。小さなプログラムなら10k以下になるはずです。もし、小さくならなかったときは、 API以外の関数(自分で作ったのはのぞく)を使っていないか調べて下さい。

<VC++編 DLL用>

DLLの場合も同様に、次のファイルをコンパイルしてリンクすればOKです。
#include <windows.h>

BOOL WINAPI DllMain (HINSTANCE hInstance, DWORD reason, LPVOID lpReserved);


BOOL  WINAPI _DllMainCRTStartup(HINSTANCE hInstance, DWORD reason, LPVOID lpReserved)
{
    return DllMain(hInstance,reason,lpReserved);
}

この方法は、MSJという本の47号に詳しく載っています。 このページはこれを見て書きました。この本には、BC++での方法も載っているのでBC++使いの人は見てみるといいでしょう。


to sdk prev next