Indiana University Indiana University Indiana University

En esta página:

  • Descripción general
  • Ejemplos de valores de segmento comunes
  • Buscar referencias de matrices fuera de límites
  • Comprobar límites de shell
  • diagnosticar valores de segmento

Descripción general

Un error de segmentación (también conocido como error de segmento) es una condición común que causa que los programas se bloqueen; a menudo se asocian con un archivo llamado core. Los valores de segmento son causados por un programa que intenta leer o escribir una ubicación de memoria ilegal.

La memoria del programa se divide en diferentes segmentos: un segmento de texto para instrucciones de programa, un segmento de datos para variables y matrices definidas en tiempo de compilación, un segmento de pila para variables temporales (o automáticas) definidas en subrutinas y funciones, y un segmento de montón para variables asignadas durante el tiempo de ejecución por funciones, como malloc (en C) y allocate (en Fortran). Para obtener más información, consulte Acerca de los segmentos de programa.

Una falla de segmento ocurre cuando una referencia a una variable cae fuera del segmento donde reside esa variable, o cuando se intenta escribir en una ubicación que se encuentra en un segmento de solo lectura. En la práctica, los valores de segmento casi siempre se deben a intentar leer o escribir un elemento de matriz inexistente, no definir correctamente un puntero antes de usarlo, o (en programas C) usar accidentalmente el valor de una variable como dirección (vea el ejemplo scanf a continuación).

Ejemplos de común segfaults

  • Por ejemplo, llamar a memset() como se muestra a continuación podría provocar que un programa violación de segmento:
    memset((char *)0x0, 1, 100);
  • Los tres casos siguientes ilustran los tipos más comunes de la matriz de los relacionados con la segfaults:

    Caso

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

    Caso B

    /* Illegal memory access if value of n is not in the range 0, 1, ... 999 */ int n; int foo; for (int i = 0; i < n ; i++) foo = i;

    asunto C

    /* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2 = 1.0;

    • En el caso a, la matriz de foo está definido por index = 0,1, 2, ... 999. Sin embargo, en la última iteración del bucle for, el programa intenta acceder a foo. Esto dará lugar a un error de segmento si esa ubicación de memoria se encuentra fuera del segmento de memoria donde reside foo. Incluso si no causa un error de segmento, sigue siendo un error.
    • En el caso B, integer n podría ser cualquier valor aleatorio. Como en el caso A, si no está en el rango 0, 1, ... 999, puede causar un error de segmento. Ya sea que lo haga o no, sin duda es un error.
    • En el caso C, se ha pasado por alto la asignación de memoria para la variable foo2, por lo que foo2 apuntará a una ubicación aleatoria en la memoria. Acceder a foo2 probablemente resultará en un error de segmento.
  • Otro error de programación común que conduce a segfaults en la supervisión en el uso de punteros. Por ejemplo, la función C scanf() espera la dirección de una variable como segundo parámetro; por lo tanto, lo siguiente probablemente causará que el programa se bloquee con una falla de segmento:
    int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */

    La variable foo podría definirse en la ubicación de memoria 1000, pero la llamada a función anterior intentaría leer datos enteros en la ubicación de memoria 0 de acuerdo con la definición de foo.

  • Se producirá una falla de segmento cuando un programa intente operar en una ubicación de memoria de una manera que no está permitida (por ejemplo, los intentos de escribir una ubicación de solo lectura resultarían en una falla de segmento).
  • Los valores de segmento también pueden ocurrir cuando el programa se queda sin espacio en la pila. Esto puede no ser un error en su programa, pero puede deberse a que su shell estableció un límite de tamaño de pila demasiado pequeño.

Buscar referencias de matrices fuera de límites

La mayoría de los compiladores de Fortran tienen una opción que insertará código para verificar los límites de todas las referencias de matrices durante el tiempo de ejecución. Si un acceso cae fuera del rango de índice definido para una matriz, el programa se detendrá y le dirá dónde ocurre esto. Para la mayoría de compiladores Fortran, la opción es -C, o -check seguida de una palabra clave. Consulte la guía del usuario de su compilador para obtener la opción exacta. Utilice la comprobación de límites solo al depurar, ya que ralentizará su programa. Algunos compiladores de C también tienen una opción de comprobación de límites.

Comprobar los límites del shell

Como se ha señalado en el último ejemplo anterior, algunos problemas de error de segmento no se deben a errores en el programa, sino que se deben a que los límites de memoria del sistema se establecen demasiado bajos. Por lo general, es el límite en el tamaño de la pila lo que causa este tipo de problema. Para comprobar los límites de memoria, utilice el comando ulimit en bash o ksh, o el comando limit en csh o tcsh. Intente configurar el tamaño de pila más alto y, a continuación, vuelva a ejecutar el programa para ver si la falla de segmento desaparece.

Utilice depuradores para diagnosticar valores de segmento

Si no puede encontrar el problema de otra manera, puede probar un depurador. Por ejemplo, puede usar el conocido depurador de GNU GDBpara ver la traza inversa de un archivo corevolcado por su programa; siempre que los programas fallan, normalmente volcan el contenido de (su sección de) la memoria en el momento del bloqueo en un archivo core. Inicie el depurador con el comando gdb core, y luego use el comando backtrace para ver dónde estaba el programa cuando se bloqueó. Este sencillo truco te permitirá centrarte en esa parte del código.

Si el archivo backtrace en el archivo coreg no encuentra el problema, es posible que tenga que ejecutar el programa bajo control de depurador y, a continuación, pasar por el código una función, o una línea de código fuente, a la vez. Para hacer esto, necesitará compilar su código sin optimización, y con la bandera -g, por lo que la información sobre las líneas de código fuente se incrustará en el archivo ejecutable. Para obtener más información, consulte Ejemplo paso a paso para usar GDB dentro de Emacs para depurar un programa C ORC++.

documentos Relacionados

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *