2011-11-19 9 views
11

Ecco un programma "Ciao mondo" che utilizza WriteFile di WinAPI (compilato in Microsoft Visual C++ 2008 Express):Perché WriteFile si arresta in modo anomalo durante la scrittura sullo standard output?

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    wchar_t str[] = L"Hello world"; 

    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); 
    if(out && out!=INVALID_HANDLE_VALUE) 
    { 
     WriteFile(out, str, sizeof(str), NULL, NULL); 
     CloseHandle(out); 
    } 

    return 0; 
} 

Se eseguito in una finestra di console, si saluta felicemente il mondo. Se si tenta di reindirizzare il suo standard di uscita, tuttavia, come in

crash
hello.exe > output.txt 

il programma in WriteFile (NULL pointer eccezione). Tuttavia, output.txt esiste e contiene l'output corretto nella sua interezza.

La chiamata pila su incidente:

[email protected]() + 0x75 bytes  
[email protected]() + 0x4e bytes  
srgprc2.exe!wmain(int argc=1, wchar_t * * argv=0x00483d88) Line 15 + 0x16 bytes C++ 

Il messaggio: "L'eccezione non gestita in 0x75ce85ea (KernelBase.dll) in srgprc2.exe: 0xC0000005:. Violazione di accesso scrittura posizione 0x00000000"

Cosa sta succedendo qui? Grazie!

+3

Rimuovere la chiamata CloseHandle(). –

+0

... come dovrebbe essere chiaro, dal momento che stai usando una funzione 'Get ...', non una funzione 'Apri ...'. –

+0

CloseHandle non viene nemmeno chiamato, l'arresto si verifica in WriteFile e il programma termina. – user38329

risposta

17

Il quarto parametro su WriteFileis not optional. Stai passando NULL, che non è permesso.

+3

D'OH! "Questo parametro può essere NULL solo quando il parametro lpOverlapped non è NULL." http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx – Mordachai

+0

Grazie. Il "__out_opt" nel prototipo mi ha confuso. – user38329

+0

Ho anche lo stesso problema dell'OP menzionato nella domanda. E per quanto mi ricordo, ho anche passato NULL per quel parametro. Quindi ... Grazie per la tua grande risposta. e sì ... +1 :) –

0

4 ° parametro (che ci dice quanto byte erano effettivamente scritto) si aspetta puntatore al valore DWORD (int aka unsigned) quando si passa NULL per il parametro si tenta di scrivere DWORD puntatore nullo che causa eccezione, non solo è obbligatorio passare il puntatore a quell'argomento, ma dovresti sempre controllare il suo valore dopo la scrittura perché c'è una probabilità anche se sottile che WriteFile scriverà meno dati di quelli che hai fornito.