VC制作的软件,从VC2005之后的都需安装运行库才可以运行,从xp到win10一直都没改变,而且这货,上下版本还不能互相兼容orz这就是为啥在添加和删除程序里能看到各版本VC运行库的原因。
在某些情况下,比如绿色软件或者在pe下运行的软件,运行库可能带不全或者不好安装,于是制作一个不需要VC运行库的程序就是很有必要的了
首先创建一个VC2015的Win32 Project,选择默认选项创建一个窗体程序
打开菜单Project-> xxx Property(xxx是项目名)或者直接按Alt+F7,
选择Configuration为All Configuration, Platform为All Platform
将Basic Runtime Checks改为Default
将Security Check改为Disable Security Check(/GS-)
在stdafx.h的#progma once下面添加:
<code class="lang-cpp">#ifdef _DEBUG
#pragma comment (linker, "/nodefaultlib:msvcrtd.lib")
#else
#pragma comment (linker, "/nodefaultlib:msvcrt.lib")
#endif</code>
这时候编译一般会出现一堆堆的错误
首先解决LNK2001 unresolved external symbol wWinMainCRTStartup, wWinMainCRTStartup是VC的CRT定义的Win32程序入口点,MFC程序为WinMainCRTStartup,控制台和DLL为mainCRTStartup和_DllMainCRTStartup。
没有了运行库就没有了入口点orz没有入口点就创建一个咯,wWinMainCRTStartup不接收任何参数,我写的入口如下,可以放在stdafx.cpp里:
<code class="lang-cpp">int __cdecl wWinMainCRTStartup() {
STARTUPINFO info;
info.cb = sizeof(STARTUPINFO);
GetStartupInfo(&info);
int ret = wWinMain(GetModuleHandle(NULL),
0,
GetCommandLine(),
info.dwFlags & STARTF_USESHOWWINDOW ? info.wShowWindow : SW_SHOWDEFAULT);
ExitProcess(ret);
return ret;
}</code>
之后应该就可以顺利编译工程了,这样制作出来的程序和静态链接的程序比起来,体积极小
本方法并不是完美的,有这些缺点:
C++的异常不能用了, new delete也不能用了,也就是说这时候C++基本完全废了
C和C++的标准库大部分也都不能用了,不过这个有解决方法,我自己想出来的,可能不是很完美,就是手动实现某些stdlib里的函数,给了些常用的实现,都是互联网上搜索的:<code class="lang-cpp">void* __cdecl malloc(ULONG_PTR uSize) {
return (void *)HeapAlloc(GetProcessHeap(), 0, uSize);
}
void __cdecl free(LPVOID pMemBlock) {
HeapFree(GetProcessHeap(), 0, (LPVOID)pMemBlock);
}
#pragma function(memcpy)
void* memcpy(void * dst, const void * src, size_t count)
{
void * ret = dst;
#if defined (_M_IA64)
{
extern void RtlMoveMemory(void *, const void *, size_t count);
RtlMoveMemory(dst, src, count);
}
#else /* defined (_M_IA64) */
/*
* copy from lower addresses to higher addresses
*/
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
#endif /* defined (_M_IA64) */
return(ret);
}
#pragma function(memset)
void* __cdecl memset(void* src, int c, size_t count) {
char *tmpsrc = (char*)src;
while (count--)
*tmpsrc++ = (char)c;
return src;
}</code>
有的时候编译会看到俩错误,找不到__imp__invalid_parameter_noinfo和__imp__errno,并不晓得这俩是啥,于是空函数代替之:
<code class="lang-cpp">extern "C" void __cdecl __imp__invalid_parameter_noinfo() {
}
extern "C" void __cdecl __imp__errno() {
}</code>
还有个说不清的问题,就是调用COM组件的时候有点奇怪。。还有,MFC不适用!也就是说,复杂的软件就不要用这种方法咯参考
XXXXXXXXXXXXXXXXXXXXXXXX/t/80005XXXXXXXXXXXXXXXXXXXXXXXX/questions/2938966/how-to-use-vc-intrinsic-functions-w-o-run-time-library
200字以内,仅用于支线交流,主线讨论请采用回复功能。