2015-06-05 7 views
6

Per esempio, questa applicazione:Perché le mie applicazioni CRT-free si bloccano in modo intermittente all'avvio?

#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); 
} 

incorporato in Visual Studio 2010 come applicazione a 64 bit senza runtime C, questo funziona perfettamente - la maggior parte del tempo. A volte inizierà a bloccarsi all'avvio senza una ragione apparentemente chiara. Questo arresto si verifica prima che venga eseguito qualsiasi codice nell'applicazione (vedere di seguito).

Quando si verifica il problema, si verifica solo per una particolare istanza dell'eseguibile, ovvero un particolare file eseguibile. Una copia identica byte-by-byte del file verrà eseguita normalmente. Il problema potrebbe scomparire (sarà?) Quando il computer viene riavviato. Sto eseguendo dei test per provare a riprodurre il problema in modo affidabile, in modo da poter identificare le circostanze in cui può verificarsi il problema, ad es. Solo se è installato Visual Studio? Solo se è installato l'anti-virus? Ma finora non ho avuto molto successo nel riprodurre il problema con una procedura diversa dalla fortuna.

La maggior parte delle volte, il debug mostra che kernel32! BaseThreadInitTunk sta chiamando un indirizzo non valido anziché l'indirizzo di NoCRTMain, anche se alcune recenti esecuzioni hanno avuto esito negativo prima, apparentemente durante il caricamento delle DLL.

Credo di aver rintracciato il problema fino a quando ImageBase non è stato impostato correttamente quando il modulo è stato caricato. In un esempio di lavoro, un'immagine della memoria a 0x00D8 rispetto al modulo eseguibile, struttura _IMAGE_OPTIONAL_HEADER64 da 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 

mostra che ImageBase (gli ultimi otto byte) contiene l'indirizzo iniziale del modulo, in questo caso 1`3f590000. In un esempio in mancanza, la stessa memoria discarica

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 

mostra che ImageBase, piuttosto che essere 1`3fc60000 come previsto, è 1`3f8f0000.

Questo sembra verificarsi prima del primo punto in cui un debugger può esaminare il processo, quindi non sono sicuro di come procedere. Forse ho bisogno di fare il debug del kernel? Al momento ho una macchina virtuale VMware vSphere che presenta il problema e ho uno snapshot a cui posso tornare, quindi posso permettermi di sperimentare.

Quindi:

  • qualcuno sa la causa di questo comportamento, e ancora più importante, come prevenirlo?

  • è la mia interpretazione del dump della memoria errato?

  • suggerimenti di debug/risoluzione problemi?

opzioni del compilatore:

opzioni
/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 

Linker:

/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: guardando quale delle mie applicazioni sono noti per avere fallito in questo modo e che non lo sono, ho sospetto che il problema si verifica solo per i file eseguibili con dimensioni inferiori a una pagina (4096 byte).

+0

Re: _ "Una copia identica byte byte del file verrà eseguita normalmente.Il problema potrebbe scomparire quando scomparirà il computer." _ Mi suggerisce che il problema non è strettamente all'interno il tuo codice sorgente, ma forse con il processo di collegamento/caricamento. Potrebbe darsi che mancano alcune informazioni nell'eseguibile, che portano il caricatore del sistema operativo a "indovinare" alcuni parametri (a volte erroneamente) ea mettere in cache quell'ipotesi. – stakx

+0

Come si compila e si collega il codice? Potresti aggiungere le relative impostazioni/riga di comando alla tua domanda? – stakx

+0

@stakx: grazie; Ho aggiunto le righe di comando del compilatore e del linker. –

risposta

1

Un anno dopo, sono finalmente fiducioso nel sostenere che il suggerimento di Hans ha funzionato perfettamente: se l'applicazione è stata creata con le opzioni /DYNAMICBASE:NO e /FIXED:YES, il problema non si verifica.

Problemi correlati