c++ - que - segmentation fault(core dumped) c
¿Qué es una falla de segmentación? (12)
En palabras sencillas: la falla de segmentación es el sistema operativo que envía una señal al programa diciendo que ha detectado un acceso de memoria ilegal y que finaliza prematuramente el programa para evitar que la memoria se dañe.
¿Qué es una falla de segmentación? ¿Es diferente en C y C ++? ¿Cómo se relacionan las fallas de segmentación y los punteros colgantes?
Hay varias explicaciones buenas de "Fallo de segmentación" en las respuestas, pero dado que con el fallo de segmentación a menudo hay un volcado del contenido de la memoria, quería compartir dónde está la relación entre la parte "núcleo volcado" en el fallo de Segmentación (núcleo volcado) y la memoria viene de
Desde alrededor de 1955 hasta 1975, antes de la memoria de los semiconductores, la tecnología dominante en la memoria de la computadora usaba diminutas donas magnéticas en los cables de cobre. Las donas se conocían como "núcleos de ferrita" y la memoria principal se conocía como "memoria central" o "núcleo".
Tomado de here .
La falla de segmentación es un tipo específico de error causado por el acceso a la memoria que "no te pertenece". Es un mecanismo auxiliar que evita que la memoria se corrompa y que se introduzcan errores de memoria difíciles de depurar. Cada vez que obtiene un error de seguridad, sabe que está haciendo algo mal con la memoria: accediendo a la variable que ya se ha liberado, escribiendo en una parte de solo lectura de la memoria, etc. La falla de segmentación es esencialmente la misma en la mayoría de los idiomas que le permiten meterse con la memoria. En la gestión de la memoria, no hay una diferencia principal entre los segregados en C y C ++.
Hay muchas formas de obtener un fallo de seguridad, al menos en los lenguajes de nivel inferior, como C (++). Una forma común de obtener una falla de seguridad es eliminar la referencia de un puntero nulo:
int *p = NULL;
*p = 1;
Otro error de seguridad ocurre cuando intenta escribir en una parte de la memoria que estaba 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 que cuelga 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 finalizó el bloque. Y cuando intentes desreferenciar el puntero colgante (como *p=''A''
), probablemente obtendrás una falla de seguridad.
La página Segmentation_fault de Wikipedia tiene una descripción muy buena al respecto, solo señala las causas y razones. Echa un vistazo a la wiki para una descripción detallada.
En computación, un fallo de segmentación (a menudo acortado a segfault) o una infracción de acceso es un fallo provocado por el hardware con protección de memoria, que notifica a un sistema operativo (SO) sobre una infracción de acceso a la memoria.
Las siguientes son algunas de las causas típicas de una falla de segmentación:
- Desreferenciación de los punteros nulos: este es un caso especial del hardware de administración de memoria
- Intentar acceder a una dirección de memoria inexistente (espacio de direcciones fuera del proceso)
- Al intentar acceder a la memoria, el programa no tiene derechos (como las estructuras del núcleo en el contexto del proceso)
- Intentar escribir memoria de solo lectura (como el segmento de código)
Estos a su vez a menudo son causados por errores de programación que resultan en un acceso de memoria no válido:
Desreferenciación o asignación a un puntero no inicializado (puntero salvaje, que apunta a una dirección de memoria aleatoria)
Desreferenciación o asignación a un puntero liberado (puntero colgante, que apunta a la memoria que se ha liberado / desasignado / eliminado)
Un desbordamiento de búfer.
Un desbordamiento de pila.
Intentando ejecutar un programa que no se compila correctamente. (Algunos compiladores emitirán un archivo ejecutable a pesar de la presencia de errores en tiempo de compilación).
Para ser honesto, como han mencionado otros carteles, Wikipedia tiene un muy buen artículo sobre esto, así que eche un vistazo allí. Este tipo de error es muy común y, a menudo, se denomina otra cosa, como una infracción de acceso o un error de protección general.
No son diferentes en C, C ++ o cualquier otro lenguaje que permita apuntadores. Este tipo de errores generalmente son causados por punteros que son
- Se usa antes de iniciarse correctamente
- Se utiliza después de que la memoria a la que apuntan se haya reasignado o eliminado.
- Se utiliza en una matriz indexada donde el índice está fuera de los límites de la matriz. Esto es generalmente solo cuando estás haciendo punteros matemáticos en arrays tradicionales o cadenas en C, no en colecciones basadas en STL / Boost (en C ++).
Según wikipedia:
Se produce un fallo de segmentación cuando un programa intenta acceder a una ubicación de memoria a la que no se le permite acceder, 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).
Si bien la respuesta de Zoul explica qué es una falla de segmentación, he descubierto que este tipo de errores pueden ser especialmente 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 una Fallo de segmentación en su programa:
Cadena de control de formato incorrecto en las sentencias printf
o scanf
La cadena de control de formato debe tener el mismo número de especificadores de conversión ( %s
, %d
etc.) que el printf
o scanf
tiene argumentos para imprimir o leer. Lo mismo se 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 ubicará los datos que lee. El operador &
(dirección de) se utiliza para suministrar la dirección de una variable.
Referencias de matriz fuera de los límites
Asegúrese de no haber violado los límites de cualquier matriz que esté utilizando; es decir, no ha subcripto 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 dichas 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 que ha inicializado todos los punteros para apuntar a un área de memoria válida.
Uso incorrecto de los operadores &
(dirección de) y *
(desreferenciación)
Deberá tener cuidado al usar estos, especialmente al pasar parámetros por referencia / usando punteros.
Límites de Shell
A veces, las fallas de segmentación no son causadas por errores en el programa, sino porque los límites de la memoria del sistema son demasiado bajos. Por lo general, es el límite de tamaño de pila el que causa este tipo de problema (desbordamientos de pila). Para verificar los límites de memoria, use el ulimit
en bash
.
Depuración utilizando gdb
Puede usar el depurador gdb
para ver el seguimiento del archivo del core
descargado por su programa. Cuando los programas funcionan de forma predeterminada, por lo general, vuelcan el contenido de la memoria en el momento del bloqueo en un archivo del core dumped
( core dumped
). Compile su programa con la bandera -g
, ejecute en gdb
y use bt
(backtrace).
Un fallo de segmentación es causado por una solicitud de una página que el proceso no ha incluido en su tabla de descriptores, o por una solicitud no válida de una página que sí tiene (por ejemplo, una solicitud de escritura en una página de solo lectura).
Un puntero colgante es un puntero que puede o no apuntar a una página válida, pero sí a un segmento de memoria "inesperado".
Una falla de segmentación o una violación de acceso ocurre cuando un programa 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 se produce 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).
Valdría la pena tener en cuenta que la falla de segmentación no se debe al acceso directo a otra memoria de proceso (esto es lo que oigo 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 utilizando ningún valor de puntero. Una excepción a esto puede ser las bibliotecas compartidas que son el mismo espacio físico de direcciones asignadas a (posiblemente) diferentes direcciones virtuales y memoria del kernel que incluso se asignan de la misma manera en cada proceso (para evitar el vaciado de TLB en syscall, creo). Y cosas como shmat;): esto es lo que yo cuento como acceso "indirecto". Sin embargo, se puede verificar que usualmente se encuentran lejos del código de proceso y generalmente podemos acceder a ellos (es por eso que están allí, sin embargo, acceder a ellos de manera incorrecta producirá 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 incorrecta (por ejemplo, tratando de escribir en un espacio no grabable). Pero la razón más común de esto es el acceso a la parte del espacio de direcciones virtuales que no se asigna a ninguna física.
Y todo esto con respecto a los sistemas de memoria virtual.
La falla de segmentación ocurre cuando un proceso (instancia en ejecución de un programa) está tratando de acceder a la dirección de memoria de solo lectura o al rango de memoria que está siendo usado por otro proceso o al acceso a la dirección de memoria no válida (no válida). El problema de referencia (puntero) que cuelga significa que se intenta acceder a un objeto o variable cuyo contenido ya se ha eliminado de la memoria, por ejemplo:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
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 una prueba podría ayudarlo.
La solución en este caso, cambiar la memoria RAM.
editar:
Aquí hay una referencia: Fallo de segmentación por hardware.