¿Qué es una falla de segmentación?

¿Qué es una falla de segmentación? ¿Es diferente en C y C ++? ¿Cómo se relacionan las fallas de segmentación y los indicadores colgantes?

La falla de segmentación es un tipo específico de error causado por el acceso a la memoria que “no le pertenece”. Es un mecanismo de ayuda que evita que corrompa la memoria e introduce errores de memoria difíciles de depurar. Cada vez que obtienes un segfault sabes que estás haciendo algo mal con la memoria, accediendo a la variable que ya ha sido liberada, escribiendo en una porción de solo lectura de la memoria, etc. La falla de segmentación es esencialmente la misma en la mayoría de los lenguajes que te dejan jugar la gestión de memoria, no hay diferencia principial entre segfaults en C y C ++.

Hay muchas maneras de obtener una segfault, al menos en los lenguajes de nivel inferior como C (++). Una forma común de obtener una segfault es desreferenciar un puntero nulo:

 int *p = NULL; *p = 1; 

Otro segfault sucede cuando intenta escribir en una parte de la memoria marcada como de solo lectura:

 char *str = "Foo"; // Compiler marks the constant string as read-only *str = 'b'; // Which means this is illegal and results in a segfault 

El puntero colgante apunta a una cosa que ya no existe, como aquí:

 char *p = NULL; { char c; p = &c; } // Now p is dangling 

El puntero p cuelga porque apunta a la variable de carácter c que dejó de existir después de que terminó el bloque. Y cuando intenta desviar el puntero colgante (como *p='A' ), probablemente obtenga un segfault.

Vale la pena señalar que la falla de segmentación no es causada por el acceso directo a otra memoria de proceso (esto es lo que estoy escuchando a veces), ya que simplemente no es posible. Con la memoria virtual cada proceso tiene su propio espacio de direcciones virtuales y no hay forma de acceder a otro usando cualquier valor de puntero. Excepción a esto pueden ser bibliotecas compartidas que son el mismo espacio de direcciones físicas mapeadas (posiblemente) diferentes direcciones virtuales y memoria del kernel que incluso se mapean de la misma manera en cada proceso (para evitar la descarga de TLB en syscall, creo). Y cosas como shmat;) – esto es lo que cuento como acceso “indirecto”. Sin embargo, se puede verificar que generalmente se encuentran muy lejos del código de proceso y que usualmente podemos acceder a ellos (esta es la razón por la que están allí, sin embargo, acceder a ellos de forma incorrecta generará un error de segmentación).

Aún así, la falla de segmentación puede ocurrir en el caso de acceder a nuestra propia memoria (proceso) de manera inadecuada (por ejemplo, tratando de escribir en un espacio no modificable). Pero la razón más común es el acceso a la parte del espacio de direcciones virtuales que no está mapeada en forma física.

Y todo esto con respecto a los sistemas de memoria virtual.

Una falla de segmentación es causada por una solicitud de una página que el proceso no tiene enumerado en su tabla de descriptores, o una solicitud no válida para una página que sí aparece (por ejemplo, una solicitud de escritura en una página de solo lectura).

Un puntero colgante es un puntero que puede apuntar o no a una página válida, pero apunta a un segmento de memoria “inesperado”.

Para ser honesto, como han mencionado otros carteles, Wikipedia tiene un artículo muy bueno sobre esto, así que eche un vistazo allí. Este tipo de error es muy común y a menudo se denomina otras cosas, como la Infracción de acceso o la Falla de protección general.

No son diferentes en C, C ++ o en cualquier otro lenguaje que permita punteros. Este tipo de errores generalmente son causados ​​por punteros que son

  1. Utilizado antes de ser inicializado correctamente
  2. Usado después de que la memoria que señalan ha sido reasignada o eliminada.
  3. Se usa en una matriz indexada donde el índice está fuera de los límites de la matriz. Por lo general, esto solo ocurre cuando se realizan cálculos de puntero en matrices tradicionales o cadenas de caracteres, no en colecciones basadas en STL / Boost (en C ++).

Si bien la respuesta de Zoul explica qué es una falla de segmentación, he descubierto que este tipo de errores pueden ser particularmente difíciles de detectar, especialmente si eres nuevo en lenguajes de bajo nivel como C ++ o C. Estas son algunas de las formas comunes de obtener un falla de segmentación en su progtwig:

Cadena de control de formato incorrecta en instrucciones printf o scanf

La cadena de control de formato debe tener el mismo número de especificadores de conversión ( %s , %d etc.) ya que printf o scanf tiene argumentos para imprimir o leer. Lo mismo aplica para fprintf y fscanf .

No usar & en los argumentos para scanf

La función scanf toma como argumentos la cadena de control de formato y las direcciones de las variables en las que colocará los datos que lee. El operador & (dirección de) se utiliza para proporcionar la dirección de una variable.

Referencias de matriz fuera de límites

Asegúrese de no haber violado los límites de ninguna matriz que esté utilizando; es decir, no ha subscrito la matriz con un valor menor que el índice de su elemento más bajo o mayor que el índice de su elemento más alto. Valgrind puede ser útil para detectar tales referencias: puede usar valgrind con el --tool=exp-sgcheck .

Acceso a punteros no inicializados

A una variable de puntero se le debe asignar una dirección válida antes de acceder. Asegúrese de haber inicializado todos los punteros para señalar un área de memoria válida.

Uso incorrecto de los operadores & (dirección de) y * (desreferencia)

Debería tener cuidado al usar estos, especialmente al pasar parámetros por referencia / usar punteros.

Límites de Shell

A veces, las fallas de segmentación no son causadas por errores en el progtwig, sino que son causadas por límites de memoria del sistema demasiado bajos. Por lo general, es el límite en el tamaño de la stack lo que causa este tipo de problema (desbordamientos de stack). Para verificar los límites de memoria, use el ulimit en bash .

Depuración usando gdb

Puede usar el depurador gdb para ver la traza inversa del archivo core descargado por su progtwig. Siempre que los progtwigs segmentan por defecto, por lo general vuelcan el contenido de la memoria en el momento del choque en un archivo core dumped ( core dumped ). Comstack tu progtwig con el indicador -g , ejecuta en gdb y usa bt (backtrace).

De acuerdo con wikipedia:

Se produce un error de segmentación cuando un progtwig intenta acceder a una ubicación de memoria a la que no tiene acceso, o intenta acceder a una ubicación de memoria de una manera que no está permitida (por ejemplo, intentar escribir en una ubicación de solo lectura, o sobrescribir parte del sistema operativo).

La falla de segmentación también es causada por fallas de hardware, en este caso, las memorias RAM. Esta es la causa menos común, pero si no encuentra un error en su código, tal vez un memtest podría ayudarlo.

La solución en este caso, cambie la RAM.

editar:

Aquí hay una referencia: falla de segmentación por hardware

La falla de segmentación ocurre cuando un proceso (instancia en ejecución de un progtwig) intenta acceder a la memoria de solo lectura o al rango de memoria que está siendo utilizado por otro proceso o acceder a la dirección de memoria inexistente (no válida). Problema de referencia colgante (puntero) significa que intenta acceder a un objeto o variable cuyos contenidos ya han sido eliminados de la memoria, por ejemplo:

 int *arr = new int[20]; delete arr; cout< 

La página Segmentation_fault de Wikipedia tiene una muy buena descripción al respecto, solo señala las causas y los motivos. Eche un vistazo a la wiki para una descripción detallada.

En informática, una falla de segmentación (a menudo acortada a segfault) o una violación de acceso es una falla planteada por el hardware con protección de memoria, notificando a un sistema operativo (SO) sobre una violación de acceso a la memoria.

Las siguientes son algunas de las causas típicas de un error de segmentación:

  • Desreferencia de punteros NULL – esto es especial-revestido por hardware de administración de memoria
  • Intentar acceder a una dirección de memoria inexistente (espacio de direcciones externo al proceso)
  • Intentar acceder a la memoria del progtwig no tiene derechos (como las estructuras del núcleo en el contexto del proceso)
  • Intentando escribir memoria de solo lectura (como segmento de código)

Estos a su vez a menudo son causados ​​por errores de progtwigción que dan como resultado un acceso a memoria no válido:

  • Desreferencia o asignación a un puntero no inicializado (puntero salvaje, que apunta a una dirección de memoria aleatoria)

  • Desreferencia o asignación a un puntero liberado (puntero colgante, que apunta a la memoria que ha sido liberada / desasignada / eliminada)

  • Un desbordamiento de búfer.

  • Un desbordamiento de stack.

  • Intenta ejecutar un progtwig que no se comstack correctamente. (Algunos comstackdores producirán un archivo ejecutable a pesar de la presencia de errores en tiempo de comstackción).

En palabras simples: la falla de segmentación es el sistema operativo que envía una señal al progtwig diciendo que ha detectado un acceso ilegal a la memoria y está terminando prematuramente el progtwig para evitar que la memoria se corrompa.

Se produce una falla de segmentación o una violación de acceso cuando un progtwig intenta acceder a una ubicación de memoria que no existe o intenta acceder a una ubicación de memoria de una manera que no está permitida.

  /* "Array out of bounds" error valid indices for array foo are 0, 1, ... 999 */ int foo[1000]; for (int i = 0; i <= 1000 ; i++) foo[i] = i; 

Aquí i [1000] no existe, por lo que ocurre segfault.

Causas de la falla de segmentación:

 it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access. De-referencing NULL pointers – this is special-cased by memory management hardware. Attempting to access a nonexistent memory address (outside process's address space). Attempting to access memory the program does not have rights to (such as kernel structures in process context). Attempting to write read-only memory (such as code segment).