2011-05-24 12 views
6

Tengo un programa llamado abc.stdout redirect cambio de salida

Cuando ejecuto el siguiente comando:

$ ./abc < infile 

me sale el siguiente resultado:

ijklm 

Sin embargo, cuando corro:

$ ./abc <infile> outfile 
$ cat outfile 

me da este resultado:

ijkoo 

Ahora, asumo que esto es un error en mi programa. Sin embargo, independientemente de lo que esté haciendo mi programa, no sé cómo es posible.

EDIT:

Ahora que sé que es posible, estoy curioso en cuanto a lo que está en mi programa que está causando esto.

hay un bloque dentro de un bucle en mi programa que contiene:

byte = ascii_to_byte(asciibyte); 
putchar(byte); 

byte es de tipo char.

Ahora si cambio putchar(byte) a printf("%c", byte) toda la salida se mantiene igual.

Sin embargo, si la cambio a printf("%d", byte), entonces $ ./abc < infile salidas:

105106107111111 

que es la representación decimal de los caracteres ASCII como lo fueron en outfile. Pero no es la representación decimal de los personajes tal como aparecieron cuando se enviaron a stdout. No entiendo por qué podría haber esta diferencia.

editar # 2:

Si cambio de la línea de impresión a printf("%c\n", byte), entonces $ ./abc < infile salidas:

i 
j 
k 
o 
o 

Esto es consistente con lo que entra en archivo_salida. De nuevo, no estoy seguro de cuál es la diferencia.

editar # 3

Acabo de probar esto en una máquina de 32 bits, y el funcionamiento del programa: outputfile contiene ijklm. Wierd.

editar # 4

Esta es la función principal:

int main() 
{ 
    char asciibyte[8]; 
    char byte; 

    int c; //Using int to avoid the EOF pitfall. 
    long charcount = 0; 

    while((c = getchar()) != EOF){ 
     if(c != '0' && c != '1'){ 
      continue; 
     } 
     asciibyte[charcount % 8] = c; 
     if(charcount % 8 == 7){ 
      /*Testing revealed that at this point asciibyte does contain 
      what it should contain, eight ASCII ones and zeros representing 
      a byte read in from stdin*/ 
      byte = ascii_to_byte(asciibyte); 
      /*Print statements such as: 
       printf("%d", byte); 
       printf("%c\n", byte); 
      reveal that the ascii_to_byte function works incorrectly on my 
      64 bit machine. However these statements: 
       putchar(byte); 
       printf("%c", byte); 
      make it appear as though the function operates as it should. 
      EXCEPT if i redirect that output to a file.*/ 
      putchar(byte); 
     } 
     charcount++; 
    } 
    return 0; 
} 

Y aquí es la función ascii_to_byte:

char ascii_to_byte(char *asciibyte){ 
    char byte; 
    int i; 
    for(i = 0; i < 8; ++i){ 
     if(asciibyte[7-i] == '1'){ 
      byte = byte | (1 << i); 
     } 
    } 
    return byte; 
} 

edición final

Noté que debería haber inicializado el byte a 0x00. Problema resuelto. ¿Por qué estoy tan retrasado? Daré respuestas a quienes puedan explicar específicamente cómo esto causó el problema.

+0

¿La salida es siempre la misma? si ejecuta ./abc un par de veces, ¿obtiene el mismo resultado? –

+0

Sí, el resultado es constante en varias pruebas. – oadams

+0

cuál es la salida de './abc pmg

Respuesta

1

Es ciertamente posible: el programa podría verificar si está escribiendo en un terminal y escribir algo diferente de lo que escribiría al escribir en una tubería.

0

Lo que dice Neil Butterworth. La función se llama isatty.

if (isatty(STDOUT)) printf("I am printing to the terminal!\n"); 

Asimismo, si bien las pruebas de material, que podría haber hecho:

$ ./abc <infile> infile 

por accidente. Por lo tanto, es posible que desee comprobar rápidamente que infile realmente contiene los mismos datos.

+0

Sí, he hecho esto un montón de veces con diferentes entradas de prueba, y todavía soy extraño. – oadams

3

Este tipo de comportamiento extraño, que aparece y desaparece de acuerdo con cambios aparentemente no relacionados, es probablemente indicativo de que su programa lee o escribe en memoria y el comportamiento cambia cuando otras partes del código hacen un uso diferente de la pila y/o pila.

Me gustaría comprobar su código cuidadosamente en fealdad como desbordamientos de búfer, que devuelven punteros a variables en la pila, etc.

paso a paso por el código con un depurador bien puede ser productiva (o podría cambiar la comportamiento de nuevo si no tiene suerte!).

Hay un par de cosas interesantes que he visto:

  1. ¿Cómo puede la redirección de stdout posiblemente afectar para nada? Tal vez porque hace que la biblioteca C se comporte de una manera un tanto diferente: se usa un modo de búfer diferente para la transmisión, dependiendo de si está conectado a un dispositivo terminal o no (consulte GNU libc documentation o C99 §7.9.13, párrafo 7) .

  2. ¿Por qué cambiar a putchar(byte)printf("%c", byte) no cambia nada, cuando ambos printf("%d", byte) y printf("%c\n", byte) cambie este comportamiento? Quizás porque el compilador reescribe automáticamente printf("%c", byte) en el más eficiente putchar(byte) - las versiones vagamente recientes de GCC normalmente hacen esto, incluso cuando no hay optimizaciones habilitadas - mientras que printf("%d", byte) y printf("%c\n", byte) realmente se compilarán como llamadas al printf().

1

Como usted dice, byte es inicializado, por lo nada puede suceder.

Una de las cosas que pueden suceder es que byte "comienza" en 0 y mantiene su valor de llamada de función a llamada de función (como si se hubiera declarado static).

 
in binary ... 

    byte | c (bin) | byte | c 
-----------+--------------+-------------- 
00000000 | i (01101001) | 01101001 (i) 
01101001 | j (01101010) | 01101011 (k) * strange you get 'j', but anything can happen :) 
01101011 | k (01101011) | 01101011 (k) 
01101011 | l (01101100) | 01101111 (o) 
01101111 | m (01101101) | 01101111 (o)