みけCATのにっき(仮)
つれづれなるまゝに、日くらし、PCにむかひて、心に移りゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
(本当か!?)
出典

MSVCRT.DLLに依存しない実行ファイルを作る

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

MSVCRT.DLLに依存しない実行ファイルを作る

投稿記事 by みけCAT » 11年前

なんとなくDependency Walkerで、C言語で自作したDLLが依存するDLLを調べていたところ、"MSVCRT.DLL"というものがありました。
さらに、DLLだけでなく普通のexeファイルもこれに依存していることが分かりました。
そこで私は思いました。
o O (MS…VC?私が使っているのはgccなのに?というか、このファイルって多くのWindowsに存在するの?)
というわけで、C言語とgccでこのMSVCRT.DLLに依存しない実行ファイルが作れないか、調査してみることにしました。

ちょっと調べると、
MinGW GCCでlibcとしてmsvcrt.dll以外を使うまとめ - 自分についてのまとめサイト
というサイトが見つかりました。
o O (やったか?)
でも、よく見ると他のmsvcが入ったDLLを使っていました。これでは意味ないです。

次に、標準ライブラリを無効にしてコンパイルすることにしました。
多分、普通のWin32 APIは使ってもよいと思う[要出典]ので、GetStdHandle関数を使えば標準入出力もできます。
すると、__mainに対してundefined referenceが出ました。
-lgccを付けると、atexitという標準ライブラリに依存してしまい、ダメでした。

ということは、なんとかこの__mainという関数をでっちあげないといけなそうです。
試行錯誤の結果、結局

CODE:

int __main(void) {
	return 0;
}
だけで実行できるようで、main関数の戻り値もきちんと%ERRORLEVEL%に反映されているようです。
ただし、argc,argvを用いてコマンドラインを受け取ることは、現時点ではできないようです。(今後の課題)

また、通常のC言語では、stdin,stdoutはテキストモードですが、Win32 APIを用いるとバイナリモード相当になるようです。

今日の成果
・MSVCRT.DLLに依存しない実行ファイルでHello, worldを表示できた

CODE:

#include 

int main(void) {
	HANDLE hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
	const char* hw="Hello, world\r\n";
	DWORD written=0;
	WriteFile(hStdout,hw,lstrlen(hw),&written,NULL);
	return 0;
}

int __main(void) {
	return 0;
}
・MSVCRT.DLLに依存しない実行ファイルで標準入力から読み込んだデータを標準出力に書き出せた(ただしバイナリモード)

CODE:

#include 

int main(int argc,char* argv[]) {
	HANDLE hStdin=GetStdHandle(STD_INPUT_HANDLE);
	HANDLE hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
	DWORD written=0;
	DWORD read=0;
	char buffer[1024]={0};
	for(;;) {
		if(!ReadFile(hStdin,buffer,sizeof(buffer),&read,NULL) || read==0)break;
		WriteFile(hStdout,buffer,read,&written,NULL);
	}
	return 0;
}

int __main(void) {
	return 0;
}
MSVCRT.DLLに依存しないだけでなく、通常のputsでHello, worldを表示するexeが9,216バイトだったのに対し、
今回のHello, worldは3,072バイトと、サイズも小さくなっています。(どちらもstrip済)でも、これはおまけ程度ですね。

まだKERNEL32.DLLには依存していますが、さすがにこれはほとんどのWindowsに入っていますよね…[要出典]

今後の課題
・argc,argvに対応
・標準ライブラリの実装(signalとかsetjmpとか、ほとんど使わなそうなものは一部切り捨てていい?)

成果物を添付ファイルにしました。
オフトピック
待てよ…もしもVisual C++のライブラリを使っているなら、fopen_sとかも使えるのではないのか…?
使えないということは、別物なんじゃないのか?
添付ファイル

[拡張子 zip は無効化されているため、表示できません]


naohiro19
記事: 256
登録日時: 14年前

Re: MSVCRT.DLLに依存しない実行ファイルを作る

投稿記事 by naohiro19 » 11年前

Visual Studio のほうでランタイムライブラリの設定を「マルチスレッド(/MT)」「マルチスレッド デバッグ(/MTd)」を指定するだけVisual C++ ランタイムライブラリに依存しない実行ファイルが出来上がります。