number inputs c++ gcc

number - inputs c++



¿Por qué la salida de std:: cout desaparece completamente después de que se le envíe NULL? (3)

Me tomó un tiempo entender por qué algunas salidas de cout parecen desaparecer en el éter. El culpable:

std::cout<< "This line shows up just fine" << std::endl; const char* some_string = a_function_that_returns_null(); if (some_string == 0) std::cout<< "Let''s check the value of some_string: " << some_string << std::endl; std::cout<< "This line and any cout output afterwards will not show up" << std::endl;

La salida del fragmento de código anterior será:

This line shows up just fine Let''s check the value of some_string:

Por lo tanto, alimentar un NULL en cout deshabilitará toda la salida después. ¿Por qué? ¿Y como arreglarlo?

Esto no sucede todo el tiempo: un compañero de trabajo con el mismo código obtiene todos los resultados esperados. Y en caso de que te preguntes por qué no puedo evitar introducir NULL en cout con una sentencia if: estoy trabajando en una gran base de código, ¡y no sé dónde sucederá esto! Todo lo que sé es que las declaraciones cout que puse nunca aparecieron.

Más información:

a_function_that_returns_null() es en realidad getenv("HOST") . Verifiqué en la línea de comandos a través de echo $HOST que la variable HOST está vacía. Si export HOST= (sabor bash), todos los resultados están ahí. No tengo idea de qué contiene inicialmente la variable HOST ni qué devuelve getenv inicialmente cuando antes getenv la variable HOST; todo lo que sé es que (some_string == 0) es verdadero.


Cuando intenta generar const char* , el flujo imprime todos los bytes hasta que llega a ''/0'' . Está llevando a un comportamiento indefinido. Por ejemplo, podría imprimir algunos símbolos de control (es decir, ''/n'' , ''/r'' y así sucesivamente) y obtener un resultado impredecible.

EDITAR : En realidad, la transmisión del puntero NULL es suficiente para obtener UB. No voy a borrar mi respuesta debido a comentarios útiles.


Estoy bastante seguro de que cout << (char*)NULL tiene un comportamiento indefinido. Me temo que "No hagas eso" es el mejor consejo que puedo ofrecerte.


const char* some_string = a_function_that_returns_null();

¿Quieres decir que literalmente devuelve un puntero nulo?

[2003: 27.6.2.5.4]:

template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, const char* s);

3. Requiere: s no es nulo.

Entonces la transmisión de some_string es un comportamiento indefinido; no puede anular la referencia de un puntero para obtener una cadena, incluso una vacía, si el puntero no es válido.

Esto no sucede todo el tiempo: un compañero de trabajo con el mismo código obtiene todos los resultados esperados

UB conduce a síntomas poco fiables . El hecho de que no siempre se produzca un bloqueo puede ser un poco sorprendente, ya que la mayoría de los sistemas operativos modernos tienen el objetivo de hacer siempre SIGSEGV cuando intenta eliminar la referencia de un puntero nulo.

Sin embargo, desde un punto de vista de C ++, cualquier cosa puede pasar ; en su caso particular, la implementación de su biblioteca estándar puede estar comprobando un puntero nulo y estableciendo un indicador de error en la secuencia en lugar de intentar desreferir el puntero. Esa es su prerrogativa.

(Probablemente, también es la razón por la que fallan las siguientes operaciones de transmisión: intentar escribir en una transmisión no hace nada cuando hay un indicador de error establecido).

Por ejemplo, libstdc ++ que se envía con GCC 4.6.0, a pesar de nombrar s != 0 como condición previa , hace esto :

00325 if (!__s) 00326 __out.setstate(ios_base::badbit); 00327 else

Sin embargo, no debe confiar en este comportamiento ; ¡Podría cambiar en cualquier momento !

Entonces, simplemente no hagas esto. Transmita una cadena válida, pero vacía, si realmente debe hacerlo.

¿Y qué pasa con std::string ?