única una tener página name metadescripción keywords etiquetas etiqueta description descripcion debe content cada c++ c gcc static-analysis

c++ - una - name keywords



¿Cómo aumentar la advertencia si el valor de retorno no se tiene en cuenta? (7)

Cualquier código de análisis estático (por ejemplo, PC-Lint ) debería poder decírselo. Para PC-Lint, sé que este es el caso.

Me gustaría ver todos los lugares en mi código (C ++) que ignoran el valor de retorno de una función. ¿Cómo puedo hacerlo? ¿Con la herramienta de análisis de código estático o gcc?

Ejemplo de código incorrecto:

int f(int z) { return z + (z*2) + z/3 + z*z + 23; } int main() { int i = 7; f(i); ///// <<----- here I disregard the return value return 1; }

Tenga en cuenta que:

  • debería funcionar incluso si la función y su uso están en archivos diferentes
  • herramienta de comprobación estática gratuita

Desea el atributo warn_unused_result de GCC:

#define WARN_UNUSED __attribute__((warn_unused_result)) int WARN_UNUSED f(int z) { return z + (z*2) + z/3 + z*z + 23; } int main() { int i = 7; f(i); ///// <<----- here i disregard the return value return 1; }

Intentar compilar este código produce:

$ gcc test.c test.c: In function `main'': test.c:16: warning: ignoring return value of `f'', declared with attribute warn_unused_result

Puedes ver esto en uso en el kernel de Linux ; tienen una macro __must_check que hace lo mismo; parece que necesita GCC 3.4 o superior para que esto funcione. A continuación, encontrará esa macro utilizada en los archivos de encabezado del kernel:

unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n);


El clásico programa "pelusa" solía ser muy voluble sobre las funciones que devolvían un valor que se ignoraba. El problema era que muchas de esas advertencias no eran deseadas, lo que provocaba un ruido excesivo en la salida de pelusa (recogía trozos de pelusa que querías que ignorara). Esa es probablemente la razón por la cual GCC no tiene una advertencia estándar para eso.

El otro problema, el otro lado, es "cómo se suprime la advertencia cuando se sabe que se está ignorando el resultado, pero realmente no me importa". El escenario clásico para eso es:

if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, sighandler);

Te importa el primer resultado de signal() ; sabes que el segundo será SIG_IGN (ya que solo lo configuraste para eso). Para alejarme de las advertencias, a veces uso alguna variante en:

if ((old = signal(SIGHUP, SIG_IGN)) != SIG_IGN) old = signal(SIGHUP, sighandler);

Esto asigna al old ambas ocasiones. Puedes seguir eso con ''assert (old == SIG_IGN)''.


Por lo que sé, no hay ninguna opción de GCC para dar esta advertencia. Sin embargo, si está interesado en funciones específicas, puede etiquetarlas con un atributo:

int fn() __attribute__((warn_unused_result));

lo que daría una advertencia si el valor de retorno de fn () no se usó. Advertencia: nunca he usado esta función yo mismo.


Puede usar esta plantilla práctica para hacerlo en tiempo de ejecución.

En lugar de devolver un código de error (p. Ej., HRESULT), devuelve un código de retorno <HRESULT>, que afirma si se sale del alcance sin que se lea el valor. No es una herramienta de análisis estático, pero de todos modos es útil.

class return_value { public: explicit return_value(T value) :value(value), checked(false) { } return_value(const return_value& other) :value(other.value), checked(other.checked) { other.checked = true; } return_value& operator=(const return_value& other) { if( this != &other ) { assert(checked); value = other.value; checked = other.checked; other.checked = true; } } ~return_value(const return_value& other) { assert(checked); } T get_value()const { checked = true; return value; } private: mutable bool checked; T value; };


Un analizador estático será su mejor apuesta aquí. Aquí usamos Coverity, pero también hay herramientas gratuitas disponibles que puede usar.

Si necesita una solución rápida y sucia y tiene a mano un shell de estilo Linux, puede intentar algo como:

grep -rn "function_name" * | grep -v "="

Eso encontrará todas las líneas que hacen referencia a la función especificada, pero no contiene un "=". Puede obtener muchos falsos positivos (y potencialmente algunos falsos negativos), pero si no tiene un analizador estático, es un buen lugar para comenzar.


un analizador estático hará el trabajo por usted, pero si su código base es más que trivial, prepárese para sentirse abrumado ;-)