在VS刚刚构建完成后,"xxx.exe不是一个有效的Win32应用程序"。
在VS刚刚构建完成后,"xxx.exe不是一个有效的Win32应用程序"。
我在我的Windows-7-64位电脑上使用Visual Studio 2015(使用IDE)成功开发了一个WinAPI应用程序。通常我会在发布模式下测试程序。
然后我对源代码进行了一些编辑。程序编译和链接时没有出错,但程序的行为不完全符合我的预期,所以我切换到调试模式并尝试构建和运行。同样,VS编译和链接时没有出错,但后来却抱怨说:“无法启动程序'f:\dropbox\blah\x64\Debug\xxx.exe'.'f:\dropbox\blah\x64\Debug\xxx.exe'不是有效的Win32应用程序。”我觉得很奇怪,所以我又切换回发布模式再试了一次-程序正常启动。我进行了一些编辑和重新构建,但后来VS却报告了:“无法启动程序'f:\dropbox\blah\x64\Release\xxx.exe'.'f:\dropbox\blah\x64\Release\xxx.exe'不是有效的Win32应用程序。”我尝试了清理所有、重启VS,甚至重启电脑..但都没有用,我仍然得到完全相同的错误。
编辑: 在阅读了类似的报告后,我尝试暂停了Dropbox的同步。然后好像程序能够运行了,但只有一两次,然后问题又出现了。然后我尝试关闭多处理器编译,这似乎使得发布版本的程序能够再次运行。此后,我已经进行了多次编辑、重建和运行(50+次?)都没有问题-但它仍然拒绝运行调试版本。
编辑: 我的杀毒软件是Microsoft Security Essentials。
编辑: 调用dumpbin并传递我的(未运行的调试exe)会产生以下输出:
文件类型: 可执行映像
摘要
1000 .00cfg
77BB8000 .data
1000 .gfids
4000 .idata
4000 .pdata
31000 .rdata
4000 .reloc
1000 .rsrc
DD000 .text
编辑: 刚刚在一个完全不同的机器上(Windows-10-64位),该机器通过Dropbox链接,出现了完全相同的症状,即在发布模式下可以运行但在调试模式下不能运行。
编辑: 在Michael Burr的建议下,我对我的(不工作的)调试exe运行了dependancy walker,并报告了以下错误:
[图片链接]
出于好奇,我想看看dep-walker对我的(正常工作的)发布exe说了什么,结果发现我得到了完全相同的错误列表!...在进一步搜索后,我发现了这个SO问题,在其中得出结论:“要点是:正如其他地方的人所说,该工具现在有点过时了,在较新的操作系统上不总是正常工作。因此,请保持警惕,不要被缺少“API-MS-WIN-CORE-COM-L1-1-0.DLL”的问题所误导,...问题可能完全在其他地方。”
编辑: 我通过下图左侧的选择框在调试模式和发布模式之间切换,并通过点击绿色三角形运行程序。
[图片链接]
编辑: 我为调试exe生成了映射文件。这里面的内容太多了,但开头几行是...
[代码]
时间戳为5811bed3(2016年10月27日星期四 09:46:11)
首选加载地址为0000000140000000
起始 长度 名称 类别
0001:00000000 00002840H .text$di 代码
0001:00002840 000da860H .text$mn 代码
0001:000dd0a0 00001020H .text$mn$00 代码
0001:000de0c0 00001eb0H .text$x 代码
0001:000dff70 0000104bH .text$yd 代码
0002:00000000 00000110H .CRT$XCA 数据
0002:00000110 00000110H .CRT$XCAA 数据
0002:00000220 00000110H .CRT$XCL 数据
0002:00000330 00000128H .CRT$XCU 数据
0002:00000458 00000110H .CRT$XCZ 数据
0002:00000568 00000110H .CRT$XIA 数据
0002:00000678 00000110H .CRT$XIAA 数据
0002:00000788 00000110H .CRT$XIAC 数据
0002:00000898 00000110H .CRT$XIZ 数据
0002:000009a8 00000110H .CRT$XPA 数据
0002:00000ab8 00000110H .CRT$XPZ 数据
0002:00000bc8 00000110H .CRT$XTA 数据
0002:00000cd8 00000118H .CRT$XTZ 数据
0002:00000df0 0002c960H .rdata 数据
0002:0002d750 00000998H .rdata$r 数据
0002:0002e0e8 00000178H .rdata$zzzdbg 数据
0002:0002e260 00000110H .rtc$IAA 数据
0002:0002e370 00000188H .rtc$IMZ 数据
0002:0002e4f8 00000110H .rtc$IZZ 数据
0002:0002e608 00000110H .rtc$TAA 数据
0002:0002e718 00000188H .rtc$TMZ 数据
0002:0002e8a0 00000110H .rtc$TZZ 数据
0002:0002e9b0 00003b68H .xdata 数据
0002:00032518 00000275H .xdata$x 数据
0002:0003278d 00000000H .edata 数据
0003:00000000 000023e0H .data 数据
0003:000023e0 00000580H .data$r 数据
0003:00002960 77376001H .bss 数据
0004:00000000 0000369cH .pdata 数据
0005:00000000 00000ed0H .idata$5 数据
0005:00000ed0 000000c8H .idata$2 数据
0005:00000f98 00000018H .idata$3 数据
0005:00000fb0 00000ed0H .idata$4 数据
0005:00001e80 00001fc6H .idata$6 数据
0006:00000000 0000015eH .gfids$y 数据
0007:00000000 0000011bH .00cfg 数据
0008:00000000 00000170H .rsrc$01 数据
0008:00000170 000002ccH .rsrc$02 数据
地址 公共值 Rva+基址 Lib:Object
0000:00000000 __guard_iat_table 0000000000000000
0000:00000000 __guard_longjmp_count 0000000000000000
0000:00000000 __guard_longjmp_table 0000000000000000
0000:00000000 __guard_fids_count 0000000000000000
0000:00000000 ___safe_se_handler_table 0000000000000000
0000:00000000 ___safe_se_handler_count 0000000000000000
0000:00000000 __guard_iat_count 0000000000000000
0000:00000000 __guard_fids_table 0000000000000000
0000:00000000 __dynamic_value_reloc_table 0000000000000000
0000:00000100 __guard_flags 0000000000000100
0000:00000000 __ImageBase 0000000140000000
0001:00002aa0 ?readstring@@YAXPEAD0@Z 0000000140003aa0 f COMMAND.obj
0001:00002b70 ?make_phere@@YAXH@Z 0000000140003b70 f COMMAND.obj
0001:00002c50 ?load_snap@@YAXXZ 0000000140003c50 f COMMAND.obj
0001:00002d30 ?i_rand_0_n_inclusive@@YAHH@Z 0000000140003d30 f COMMAND.obj
[/代码]
问题原因:出现这个问题的原因是由于代码中存在一个非常大的数据段,导致可执行文件的大小接近Windows上单个可执行模块的可能大小。
解决方法:可以通过以下步骤来解决这个问题:
1. 使用以下示例C程序来获得更一致的重现:
unsigned char kaboom[0x7d000000]; int main() { return 0; }
2. 这个错误信息并不是很好,微软没有为这种情况保留错误代码。当接近0x77BB8000时,它不会重复太多。可执行映像必须适应加载器创建的内存映射文件的单个视图。这个视图在32位进程中有一个硬性的上限为2GB,并且在64位Windows版本上也有一个MMF视图大小限制。
3. 可用于数据段的空间量在每次运行时都会有所变化。从视图大小中减去的是地址空间开头和结尾的不可映射区域以及32位EXE进程中所需的操作系统DLL(至少是ntdll.dll和kernel32.dll)的空间。还有由于ASLR(地址空间布局随机化)而失去的空间,一个随机变化的数字。以及由防恶意软件和Dropbox使用的注入的DLL。
4. 无法猜测为什么你的数据段需要如此大。可以要求链接器生成一个.map文件,这样你就可以了解到该段的详细信息,大的全局变量应该会突出显示。确保目标为x64,这样你就可以有大量的地址空间可用,并使用堆(malloc等)来分配大型数组。
5. 使用链接器生成的.map文件来查找问题,.map文件会详细列出.data段的分配情况。
6. 如果可以定位到某个过大的静态数组,该数组位于“.data”段中,然后如果缩小该数组的大小,或者使用malloc来分配该数组,那么一切应该可以正常工作。
文章整理如下:
“xxx.exe is not a valid Win32 application” after VS just built it
问题原因:出现这个问题的原因是由于代码中存在一个非常大的数据段,导致可执行文件的大小接近Windows上单个可执行模块的可能大小。
解决方法:可以通过以下步骤来解决这个问题:
1. 使用以下示例C程序来获得更一致的重现:
unsigned char kaboom[0x7d000000]; int main() { return 0; }
2. 这个错误信息并不是很好,微软没有为这种情况保留错误代码。当接近0x77BB8000时,它不会重复太多。可执行映像必须适应加载器创建的内存映射文件的单个视图。这个视图在32位进程中有一个硬性的上限为2GB,并且在64位Windows版本上也有一个MMF视图大小限制。
3. 可用于数据段的空间量在每次运行时都会有所变化。从视图大小中减去的是地址空间开头和结尾的不可映射区域以及32位EXE进程中所需的操作系统DLL(至少是ntdll.dll和kernel32.dll)的空间。还有由于ASLR(地址空间布局随机化)而失去的空间,一个随机变化的数字。以及由防恶意软件和Dropbox使用的注入的DLL。
4. 无法猜测为什么你的数据段需要如此大。可以要求链接器生成一个.map文件,这样你就可以了解到该段的详细信息,大的全局变量应该会突出显示。确保目标为x64,这样你就可以有大量的地址空间可用,并使用堆(malloc等)来分配大型数组。
5. 使用链接器生成的.map文件来查找问题,.map文件会详细列出.data段的分配情况。
6. 如果可以定位到某个过大的静态数组,该数组位于“.data”段中,然后如果缩小该数组的大小,或者使用malloc来分配该数组,那么一切应该可以正常工作。