2012-06-28 11 views
5

construí la versión 3.1 del llvm/compilador-rt/ruido metálico, y estoy tratando de ver si -fcatch-undefined-comportamiento realmente hace nada. Hasta ahora, sin suerte. P.ej. Me compilar y ejecutarcomportamiento del sonido metálico no funciona como se anuncia

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    int* x = malloc(sizeof(int) * 10); 
    printf("%d\n", x[20]); 
    return 0; 
} 

con

$ /usr/local/bin/clang -fcatch-undefined-behavior undef_test.c && ./a.out 
0 

Me estoy perdiendo algo muy simple?

+2

Sí, se echa en falta que la captura/all/comportamiento indefinido es un problema muy difícil, demasiado difícil para un compilador para poner en práctica. – PlasmaHH

+1

-faddress-sanitizer debería atrapar esto, como debería valgrind. –

+0

Gracias, Ambroz. Esto fue de lo más útil. – Oleg2718281828

Respuesta

4

Sí: x no es una matriz.

Desde el documentation:

indefinido--fcatch-comportamiento: Encender la generación de código en tiempo de ejecución para comprobar si hay un comportamiento indefinido. Esta opción, que se desactiva por defecto, controla si Clang agrega controles de tiempo de ejecución para un comportamiento de tiempo de ejecución no definido. Si falla una verificación, __builtin_trap() se usa para indicar la falla. Los controles son:

  • subscripting donde el tipo estático de un operando es una variable que se decayó a partir de un tipo de matriz y el otro operando es mayor que el tamaño de la matriz o menor que cero.
  • Operadores de desplazamiento donde la cantidad desplazada es mayor o igual que el ancho de bit promovido del lado izquierdo o menor que cero.
  • Si el flujo de control llega a __builtin_unreachable.
  • Cuando llvm implementa más compatibilidad con __builtin_object_size, lee y escribe para objetos que __builtin_object_size indica que no estamos accediendo a la memoria válida. Los campos de bits y los vectores aún no se han comprobado.

supongo que quería probar el cheque subíndices, por desgracia, no construyó una matriz: se construyó un área de memoria (de malloc) y luego eligió interpretarlo como una matriz; pero desde el punto de vista del compilador, es solo un trozo de memoria (recuerde que el tipo de devolución de malloc es void*).

Probablemente se podría probar este comportamiento con:

int main() { 
    int x[10] = {}; 
    printf("%d\n", x[20]); 
} 

De lo contrario, para un seguimiento de los problemas de memoria específico, usted debe mirar en la dirección desinfectante plugin.

+0

Esto parece desencadenar una advertencia por el sonido metálico o no se especifica '-fcatch-undefined-behaviour'. – detly

+0

@detly: '-fcatch-undefined-behavior' es una opción de generación de código, que no está relacionado con advertencias; en su lugar, insertará las aserciones en tiempo de ejecución y bloqueará el programa (de manera confiable) si se viola cualquiera de esas aserciones. Por supuesto, es mejor confiar en la advertencia y actuar tan pronto como comience la compilación. Tenga en cuenta también que '-fcatch-undefined-behavior' ahora es obsoleto y debe ser el uso de' -fsanitize' para activar los distintos dirección/memoria/hilo/desinfectantes no definidos (y tener en cuenta que algunos de ellos son incompatibles entre sí) . –

1

-fcatch-undefined-behavior no maneja las referencias al puntero al azar. Para manejar este caso, el compilador tendría que almacenar el tamaño de los datos apuntados junto con el puntero y pasar ese tamaño en cada llamada a función. Eso sería incompatible con el ABI existente y requeriría recompilar todas las bibliotecas a las que pertenece su programa.

Puede argumentar que malloc es una función conocida y el compilador podría suponer que el puntero devuelto apunta a una matriz del tamaño solicitado.

Pero se estaría olvidando que malloc puede devolver NULL. Si el compilador asumió que el puntero no es NULL, optimizaría cualquier comprobación NULL (bastante peligrosa).Si el compilador asume el puntero es NULL o un puntero a un array de tamaño solicitado, que se convertiría en un poco complicado de manejar (y no hemos de hablar free y realloc aún). Además, cualquier código que elimina referencia a un puntero -ated malloc sin NULL comprobación sería considerado como un comportamiento indefinido.

Sin mencionar que su programa no puede vincular a la biblioteca estándar sino a una biblioteca que proporciona una implementación personalizada de malloc con una semántica diferente.

Cuestiones relacionadas