Fallos de segmentación en C o C++ es un error que ocurre cuando un programa intenta acceder a una ubicación de memoria a la que no tiene permiso para acceder. Generalmente, este error ocurre cuando se viola el acceso a la memoria y es un tipo de falla de protección general. Segfaults son la abreviatura de fallas de segmentación.
El volcado de memoria se refiere al registro del estado del programa, es decir, sus recursos en memoria y procesador. Intentar acceder a memoria inexistente o a memoria que está siendo utilizada por otros procesos también provoca la falla de segmentación que conduce a un volcado del núcleo.
Un programa tiene acceso a regiones específicas de la memoria mientras se ejecuta. Primero, la pila se usa para contener las variables locales para cada función. Además, es posible que tenga memoria asignada en tiempo de ejecución y guardada en el montón (nuevo en C++ y es posible que también lo escuches llamarlo tienda gratis ). La única memoria a la que el programa puede acceder es la propia (la memoria mencionada anteriormente). Se producirá un error de segmentación por cualquier acceso fuera de esa región.
La falla de segmentación es un tipo específico de error causado al acceder a la memoria que no te pertenece :
- Cuando un fragmento de código intenta realizar una operación de lectura y escritura en una ubicación de solo lectura en la memoria o en un bloque de memoria liberado, se conoce como falla de segmentación.
- Es un error que indica corrupción de memoria.
Escenarios comunes de fallas de segmentación
En una falla de segmentación, un programa intenta acceder a una memoria a la que no está autorizado o que no existe. Algunos escenarios comunes que pueden causar fallas de segmentación son:
- Modificar un literal de cadena
- Acceder a una dirección que está liberada
- Acceder a límites de índice fuera de la matriz
- Uso inadecuado de scanf()
- Desbordamiento de pila
- Desreferenciación de puntero no inicializado
1. Modificar un literal de cadena
Los literales de cadena se almacenan en la sección de solo lectura de la memoria. Es por eso que el siguiente programa puede fallar (da un error de segmentación) porque la línea *(str+1) = 'n' intenta escribir una memoria de solo lectura.
Ejemplo:
C
// C program to demonstrate segmentation fault> // by modifying a string literal> #include> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation fault> // by modifying a string literal> #include> using> namespace> std;> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }> |
>
>
Producción
tiempo de espera: el comando monitoreado descartó el núcleo
/bin/bash: línea 1: 32 Tiempo de espera de falla de segmentación 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in
Consulte Almacenamiento de cadenas en C para obtener más detalles.
2. Acceder a una dirección liberada
Aquí, en el siguiente código, se elimina la referencia al puntero p después de liberar el bloque de memoria, lo cual no está permitido por el compilador. Estos punteros se denominan punteros colgantes y producen fallos de segmento o terminaciones anormales del programa en tiempo de ejecución.
Ejemplo:
C
// C program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> #include> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(8);> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// core dump/segmentation fault> >// as now this statement is illegal> >*p = 110;> >printf>(>'%d'>, *p);> >return> 0;> }> |
3d en autocad
>
>
C++
// C++ program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> using> namespace> std;> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(>sizeof>(>int>));> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// segmentation fault> >// as now this statement is illegal> >*p = 110;> >return> 0;> }> |
>
>
Producción
Segmentation Fault>
3. Acceder al índice de matriz fuera de límites
En C y C++, acceder a un índice de matriz fuera de límites puede provocar un error de segmentación u otro comportamiento indefinido. No hay verificación de límites para matrices en C y C++. Aunque en C++, el uso de contenedores, como con el método std::vector::at() o con una declaración if(), puede evitar errores fuera de límite.
Ejemplo:
C
// C program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> int> main(>void>)> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> (0);> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> using> namespace> std;> int> main()> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> 0;> }> |
>
>
Producción
Segmentation Faults>
4. Uso inadecuado de scanf()
La función scanf() espera la dirección de una variable como entrada. Aquí, en este programa, n toma un valor de 2 y asume que su dirección es 1000. Si pasamos n a scanf(), la entrada obtenida de STDIN se coloca en la memoria 2 no válida, que debería ser 1000. Esto provoca daños en la memoria y provoca un error de segmentación.
Ejemplo:
C
// C program to demonstrate segmentation> // fault when value is passed to scanf> #include> int> main()> {> >int> n = 2;> >scanf>(>'%d'>, n);> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when value is passed to scanf> #include> using> namespace> std;> int> main()> {> >int> n = 2;> >cin>>n;> >return> 0;> }> |
>
>
java cómo convertir una cadena a int
Producción
Segementation Fault>
5. Desbordamiento de pila
No es un problema relacionado con el puntero, incluso es posible que el código no tenga un solo puntero. Es por quedarse sin memoria en la pila. También es un tipo de corrupción de memoria que puede ocurrir debido a un gran tamaño de matriz, una gran cantidad de llamadas recursivas, muchas variables locales, etc.
Ejemplo:
C
// C program to illustrate the> // segmentation fault due to> // stack overflow> #include> int> main()> {> >int> arr[2000000000];> >return> 0;> }> |
>
>
C++
// C++ program to illustrate> // the segmentation fault> // due to stack overflow> #include> using> namespace> std;> int> main()> {> >int> array[2000000000];> >return> 0;> }> |
>
>
Producción
Segmentation Fault>
6. Desbordamiento del búfer
Si los datos que se almacenan en el búfer son mayores que el tamaño asignado del búfer, se produce un desbordamiento del búfer que provoca un error de segmentación. La mayoría de los métodos en lenguaje C no realizan verificación de límites, por lo que el desbordamiento del búfer ocurre con frecuencia cuando olvidamos asignar el tamaño requerido al búfer.
Ejemplo:
C
// C program to illustrate the> // segementation fault due to> // buffer overflow> #include> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }> |
>
>
C++
// C++ program to illustrate the> // segementation fault due to> // buffer overflow> #include> using> namespace> std;> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }> |
>
>
Producción
Segmentation Fault>
7. Desreferenciar un puntero NULL o no inicializado
Es un error de programación común eliminar la referencia a un puntero no inicializado (puntero salvaje), lo que puede dar lugar a un comportamiento indefinido. Cuando se utiliza un puntero en un contexto que lo trata como un puntero válido y accede a su valor subyacente, aunque no se haya inicializado para apuntar a una ubicación de memoria válida, se produce este error. Esto puede provocar daños en los datos, errores de programa o fallos de segmentación. Dependiendo de su entorno y estado al eliminar la referencia, los punteros no inicializados pueden producir resultados diferentes.
Como sabemos, el puntero NULL no apunta a ninguna ubicación de memoria, por lo que eliminar la referencia resultará en un error de segmentación.
Ejemplo:
C
// C program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >printf>(>'%d %d'>, *ptr, *nptr);> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> using> namespace> std;> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >cout << *ptr <<>' '> << *nptr;> >return> 0;> }> |
>
>
Producción
Segmentation Fault>
¿Cómo solucionar los errores de segmentación?
Podemos solucionar los fallos de segmentación teniendo cuidado con las causas mencionadas:
- Evite modificar literales de cadena.
- Tener cuidado al utilizar punteros ya que son una de las causas más comunes.
- Considerar el tamaño del búfer y de la pila antes de almacenar los datos para evitar el desbordamiento del búfer o de la pila.
- Comprobando los límites antes de acceder a los elementos de la matriz.
- Utilice scanf() y printf() con cuidado para evitar especificadores de formato incorrectos o desbordamiento del búfer.
En general, la causa del error de segmentación es acceder a la memoria que no te pertenece en ese espacio. Mientras evitemos hacer eso, podemos evitar el error de segmentación. Si no puede encontrar la fuente del error incluso después de hacerlo, se recomienda utilizar un depurador, ya que conduce directamente al punto de error en el programa.