2011-11-19 12 views
11

He aquí un programa "Hola mundo" que utiliza escritura de archivo de API de Windows (compilado en Microsoft Visual C++ 2008 Express):¿Por qué falla WriteFile al escribir en la salida estándar?

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

Si se ejecuta en una ventana de la consola, que felizmente saluda el mundo. Si intenta redirigir la salida estándar, sin embargo, como en

accidentes
hello.exe > output.txt 

el programa de escritura de archivo (excepción de puntero nulo). No obstante, output.txt existe y contiene la salida correcta en su totalidad.

La llamada pila de accidente:

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

El mensaje: "violación de acceso de localización de escritura 0x00000000 excepción no controlada en 0x75ce85ea (KernelBase.dll) en srgprc2.exe:: 0xc0000005".

¿Qué está pasando aquí? ¡Gracias!

+3

Elimina la llamada CloseHandle(). –

+0

... como debe ser claro, ya que está utilizando una función 'Get ...', no una función 'Open ...'. –

+0

CloseHandle ni siquiera se llama, el bloqueo ocurre en WriteFile y el programa finaliza. – user38329

Respuesta

17

El cuarto parámetro para WriteFileis not optional. Estás pasando NULL, lo cual no está permitido.

+3

D'OH! "Este parámetro puede ser NULL solo cuando el parámetro lpOverlapped no es NULL". http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx – Mordachai

+0

Gracias. El "__out_opt" en el prototipo me confundió. – user38329

+0

También estoy teniendo el mismo problema que OP mencionado en la pregunta. Y, por lo que recuerdo, también pasé NULL por ese parámetro. Entonces ... Gracias por tu gran respuesta. y sí ... +1 :) –

0

cuarto parámetro (que nos dice cuánto bytes eran realmente escrito) está a la espera puntero al valor DWORD (int también conocido como sin signo) cuando se pasa NULL para ese parámetro se intenta escribir DWORD a puntero nulo que provoca excepción, no solo es obligatorio pasar el puntero a ese argumento, pero también siempre debe verificar su valor después de la escritura porque existe una probabilidad, aunque pequeña, de que WriteFile escriba menos datos de los que proporcionó.

Cuestiones relacionadas