una tipos segmento segmentacion que público proceso practico objetivo mercado empresa ejemplos ejemplo consumo clientes c++ pointers undefined-behavior

c++ - tipos - ¿Es la falla de segmentación un comportamiento indefinido real cuando nos referimos a un miembro de datos no estático?



tipos de segmentacion de clientes (3)

La regla 3.8 / 5 trata sobre el tiempo fuera de la construcción / destrucción de un objeto pero dentro de la asignación / liberación de la memoria en la que reside el objeto. A continuación se muestran los puntos fuera de la vida útil de un objeto:

void *buffer = malloc(sizeof(A)); // outside of lifetime of a // a->b is undefined A* a = new (buffer) A(); // within lifetime of a // a->b is valid a->~A(); // outside of lifetime of a // a->b is undefined free(buffer);

Técnicamente, su publicación en realidad no refleja la regla 3.8 / 5, porque no está accediendo al objeto fuera de su vida útil. Simplemente está lanzando memoria aleatoria como una instancia.

Había leído la siguiente regla y he estado tratando de escribir un ejemplo, que refleja uno. La regla es de 3.8 / 5 N3797:

Antes de que comience la vida útil de un objeto, pero después de que se haya asignado el almacenamiento que ocupará el objeto o, después de que haya finalizado la vida útil de un objeto y antes de que se reutilice o se libere el almacenamiento que ocupó el objeto, cualquier puntero que se refiera al almacenamiento Se puede usar la ubicación donde se ubicará o se ubicará el objeto, pero solo de manera limitada. Para un objeto en construcción o destrucción, ver 12.7. De lo contrario , dicho puntero se refiere al almacenamiento asignado (3.7.4.2), y usar el puntero como si el puntero fuera de tipo void* está bien definido. La indirecta a través de dicho puntero está permitida, pero el valor resultante solo se puede usar de forma limitada, como se describe a continuación. El programa tiene un comportamiento indefinido si:

[...]

- el puntero se usa para acceder a un miembro de datos no estático o llamar a una función de miembro no estático del objeto, o

[...]

El ejemplo que he escrito para:

#include <iostream> #include <typeinfo> using std::cout; using std::endl; struct A { int b = 5; static const int a = 5; }; int main() { A *p = (A*)0xa31a3442; cout << p -> a; //1, Well-fromed, there is no compile-time error cout << p -> b; //2, Segmentation fault is producing }

¿Es cierto que en el caso //1 está bien formado y no causa ningún UB , pero //2 produjo una falla de segmentación, que es UB ?


Tu preguntaste:

¿Es cierto que en el caso // 1 está bien formado y no causa ningún UB?

Las partes del estándar que citó no mencionan nada al respecto.

También preguntaste:

pero // 2 produjo un error de segmentación, que es UB?

Las partes del estándar que citó no corresponden a este comportamiento particular. Estás viendo UB debido a donde p puntos. Apunta a la memoria que no contiene un objeto válido.


Un comportamiento indefinido significa que cualquier cosa puede suceder con una implementación conforme estándar. Realmente cualquier cosa. (y tu punto 2 es UB)

Una implementación podría

  • explotar su computadora y dañarlo físicamente
  • hacer un agujero negro que trague todo el sistema solar
  • no hagas nada serio
  • enciende un poco de LED en tu teclado
  • viaja en el tiempo y mata a todos tus abuelos antes del nacimiento de tus propios padres
  • etc ....

y estar conforme (en el caso de UB); Lea también sobre la idea más familiar de los demonios nasales .

Entonces, lo que sucede en UB no es predecible y no es reproducible (en general).

Más en serio, piense un poco sobre lo que UB podría significar en la computadora conectada a los frenos ABS de su automóvil, o en algún corazón artificial , o manejando una planta de energía nuclear.

En particular, podría funcionar a veces. Como la mayoría de los sistemas operativos tienen ASLR su código tiene una pequeña posibilidad de funcionar (por ejemplo, si 0xa31a3442 apunta a alguna ubicación válida , por ejemplo, en la pila, ¡pero no lo reproducirá en la próxima ejecución!)

UB es una forma de dar libertad a los implementadores (p. Ej. De compiladores o sistemas operativos) y a las computadoras para que hagan lo que quieran, en otras palabras, para no preocuparse por las consecuencias. Esto permite, por ejemplo, optimizaciones inteligentes o buenos trucos de implementación. Pero debe preocuparse (y las consecuencias son diferentes si está codificando el sistema de control de vuelo integrado de un avión, o simplemente algunos LED de iluminación de demostración hacky con un RasberryPi, o un ejemplo simple para un curso de C ++ que se ejecuta en Linux).

Recuerde que los estándares de idiomas ni siquiera requieren ninguna computadora (o hardware) en la implementación: puede "ejecutar" su código C ++ con un equipo de esclavos humanos, pero eso sería muy poco ético (y costoso y poco confiable).

Ver también here para más referencias. Al menos deberías leer el blog de Lattner sobre Comportamiento indefinido (la mayor parte de lo que escribió para C se aplica a C ++ y muchos otros lenguajes que tienen UB).

(agregado en diciembre de 2015 y junio de 2016)

NÓTESE BIEN. La herramienta valgrind y varias opciones de depuración -fsanitize= para GCC reciente o Clang/LLVM son bastante útiles. Además, habilite todas las advertencias y la información de depuración en su compilador (por ejemplo, g++ -Wall -Wextra -g ), y use las opciones de instrumentación apropiadas como -fsanitize=undefined . Tenga en cuenta que es imposible detectar estática y exhaustivamente en tiempo de compilación todos los casos de UB (eso sería equivalente al problema de detención ).

PD. La respuesta anterior no es específica de C ++; ¡también cabe para C!