为什么我的无 CRT 应用程序在启动时会间歇性崩溃? [英] Why do my CRT-free applications intermittently crash on startup?

查看:30
本文介绍了为什么我的无 CRT 应用程序在启动时会间歇性崩溃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,这个应用程序:

#define _WIN32_WINNT 0x0500

#include <windows.h>

int __stdcall NoCRTMain(void) 
{
    int result;

    PWSTR lpCmdLine = GetCommandLine();

    for (;;)
    {
        if (*lpCmdLine == L'"') 
        {
            lpCmdLine++;
            for (;;)
            {
                if (*lpCmdLine == L'"') break;
                if (*lpCmdLine == L'\0') break;
                lpCmdLine++;
            }
        }
        if (*lpCmdLine == L' ') break;
        if (*lpCmdLine == L'\0') break;
        lpCmdLine++;
    }

    while (*lpCmdLine == ' ') lpCmdLine++;

    result = MessageBox(NULL, lpCmdLine, L"Scripting Engine", MB_OK | MB_SYSTEMMODAL);

    if (result != IDOK) for (;;) Sleep(INFINITE);

    ExitProcess(0);
}

作为没有 C 运行时的 64 位应用程序在 Visual Studio 2010 中构建,这可以完美运行 - 大多数情况下.有时它会在没有明显原因的情况下在启动时开始崩溃.此崩溃发生在应用程序中的任何代码运行之前(见下文).

Built in Visual Studio 2010 as a 64-bit application with no C runtime, this works perfectly - most of the time. Sometimes it will start crashing on startup for no readily apparent reason. This crash occurs before any of the code in the application is run (see below).

当问题发生时,它只发生在可执行文件的特定实例上,即特定的可执行文件.文件的逐字节相同副本将正常运行.当计算机重新启动时,问题可能(将?)消失.我正在运行测试以尝试可靠地重现问题,以便我可以确定可能发生问题的情况,例如,仅当安装了 Visual Studio 时?只有安装了杀毒软件吗?但到目前为止,我还没有通过任何方法来重现这个问题,但除了愚蠢的运气.

When the problem occurs, it occurs only for a particular instance of the executable, i.e., a particular executable file. An byte-by-byte identical copy of the file will run normally. The problem may (will?) disappear when the computer is rebooted. I am running tests to try to reliably reproduce the issue, so that I can identify the circumstances under which the problem can occur, e.g., only if Visual Studio is installed? Only if anti-virus is installed? But so far I haven't had much success in reproducing the problem by any procedure other than dumb luck.

大多数时候,调试显示 kernel32!BaseThreadInitThunk 调用的是无效地址而不是 NoCRTMain 的地址,尽管最近的一些运行在此之前失败,显然是在加载 DLL 时.

Most of the time, debugging shows that kernel32!BaseThreadInitThunk is calling an invalid address instead of the the address of NoCRTMain, although some recent runs have failed earlier than that, apparently while loading DLLs.

我相信我已经将问题归结为加载模块时 ImageBase 设置不正确.在一个工作实例中,在 0x00D8 处的内存转储相对于可执行模块,来自 winnt.h 的结构 _IMAGE_OPTIONAL_HEADER64:

I believe I have tracked the issue down to ImageBase being set incorrectly when the module is loaded. On a working instance, a memory dump at 0x00D8 relative to the executable module, structure _IMAGE_OPTIONAL_HEADER64 from winnt.h:

00000001`3f5900d8 0b 02 0a 00 00 02 00 00 00 06 00 00 00 00 00 00 
00000001`3f5900e8 00 10 00 00 00 10 00 00 00 00 59 3f 01 00 00 00 

显示 ImageBase(最后八个字节)包含模块的起始地址,在本例中为 1`3f590000.在失败的实例上,相同的内存转储

shows that ImageBase (the last eight bytes) contains the address of the start of the module, in this case 1`3f590000. On a failing instance, the same memory dump

00000001`3fc600d8 0b 02 0a 00 00 02 00 00 00 06 00 00 00 00 00 00 
00000001`3fc600e8 00 10 00 00 00 10 00 00 00 00 8f 3f 01 00 00 00  

显示 ImageBase 不是预期的 1`3fc60000,而是 1`3f8f0000.

shows that ImageBase, rather than being 1`3fc60000 as expected, is 1`3f8f0000.

这似乎发生在调试器可以检查进程的最早点之前,所以我不确定如何继续.也许我需要进行内核调试?我目前有一台 VMWare vSphere 虚拟机出现了该问题,而且我有一个可以恢复的快照,因此我可以进行实验.

This seems to occurs before the earliest point at which a debugger can examine the process, so I'm not sure how to proceed. Perhaps I need to do kernel debugging? I currently have a VMWare vSphere virtual machine exhibiting the problem, and I've got a snapshot I can revert to, so I can afford to experiment.

所以:

  • 有谁知道这种行为的原因,更重要的是,如何防止它?

  • does anyone know the cause of this behaviour, and more importantly, how to prevent it?

我对内存转储的理解有误吗?

is my interpretation of the memory dump mistaken?

任何调试/故障排除建议?

any debugging/troubleshooting suggestions?

编译器选项:

/Zi /nologo /W3 /WX- /O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS"
/D "_UNICODE" /D "UNICODE" /Gm- /EHsc /MT /GS- /Gy /fp:precise /Zc:wchar_t
/Zc:forScope /Fp"x64\Release\sehalt.pch" /Fa"x64\Release\" /Fo"x64\Release\"
/Fd"x64\Release\vc100.pdb" /Gd /errorReport:queue 

链接器选项:

/OUT:"C:\documents\code\w7lab-scripting\sehalt\x64\Release\sehalt.exe"
/INCREMENTAL:NO /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib"
"winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib"
"oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /NODEFAULTLIB
/MANIFEST /ManifestFile:"x64\Release\sehalt.exe.intermediate.manifest"
/ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG
/PDB:"C:\documents\code\w7lab-scripting\sehalt\x64\Release\sehalt.pdb"
/SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF 
/PGD:"C:\documents\code\w7lab-scripting\sehalt\x64\Release\sehalt.pgd"
/LTCG /TLBID:1 /ENTRY:"NoCRTMain" /DYNAMICBASE /NXCOMPAT
/MACHINE:X64 /ERRORREPORT:QUEUE 

PS:看看我的哪些应用程序已知以这种方式失败,哪些没有,我怀疑问题只发生在小于一页(4096 字节)大小的可执行文件中.

PS: looking at which of my applications are known to have failed in this way and which aren't, I suspect that the problem only occurs for executables that are less than one page (4096 bytes) in size.

推荐答案

一年过去了,我终于有信心宣称 Hans 的建议非常有效:如果应用程序是使用 /DYNAMICBASE:NO 构建的/FIXED:YES 选项,不会出现问题.

A year on, I'm finally confident in claiming that Hans' suggestion has worked perfectly: if the application is built with the /DYNAMICBASE:NO and /FIXED:YES options, the problem does not occur.

这篇关于为什么我的无 CRT 应用程序在启动时会间歇性崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆