Menu
Coddy logo textTech

¿Qué es un segmentation fault (fallo de segmentación)?

Un segmentation fault (fallo de segmentación o segfault) es un cierre abrupto que ocurre cuando un programa intenta leer o escribir memoria a la que no tiene permiso para acceder, como la dirección 0 a través de un puntero nulo. El sistema operativo detiene el programa con la señal SIGSEGV.

Por Kevin Spektor, Cofundador y CTO

Actualizado el 24 de septiembre de 2026

Un programa en C imprime su primera línea y luego se detiene con un mensaje que nadie escribió:

#include <stdio.h>

int main(void) {
    int *score = NULL;

    printf("About to read the score\n");
    printf("Score: %d\n", *score);
    return 0;
}
About to read the score
bash: line 1: 64030 Segmentation fault: 11  ./seg

Esa salida es de bash en macOS, donde 64030 es el ID del proceso y 11 es el número de la señal. En Linux el mismo fallo suele verse como Segmentation fault (core dumped) (en un sistema en español, "Violación de segmento (core generado)"). En cualquier caso, el programa nunca imprimió la puntuación. score contiene la dirección 0, y *score le pide al procesador que lea la memoria de esa dirección, algo que ningún programa tiene permitido.

Cómo se produce un segmentation fault

Cada programa se ejecuta en su propio espacio de direcciones virtual, un rango enorme de direcciones que el sistema operativo va rellenando por partes. Mapea en ese rango el código del programa, sus variables globales, su pila y su heap, en bloques llamados páginas (4 KB en la mayoría de los sistemas Linux x86, 16 KB en los Mac con Apple silicon). La mayoría de las direcciones quedan sin mapear, y la dirección 0 siempre está entre ellas para que se detecten los bugs de punteros nulos.

  1. El programa ejecuta una instrucción que lee o escribe una dirección. Aquí es la lectura de *score, la dirección 0.
  2. La unidad de gestión de memoria del procesador busca la dirección en la tabla de páginas. La página no está mapeada, o el programa intenta escribir en una página de solo lectura.
  3. El procesador detiene la instrucción y cede el control al kernel con un fallo de página.
  4. El kernel comprueba si el acceso podría ser legal, por ejemplo una pila que necesita crecer. No lo es, así que el kernel envía al proceso la señal 11, SIGSEGV.
  5. La acción por defecto de SIGSEGV es terminar el proceso y, cuando el sistema lo permite, guardar un volcado de memoria (core dump). Después el shell imprime el mensaje y fija el código de salida en 139, que es 128 más el número de la señal.

Así que un segmentation fault no lo notifica el compilador, y no es una excepción que lance el lenguaje. Es el hardware y el kernel protegiendo la memoria, lo que lo convierte en un error en tiempo de ejecución del tipo más abrupto. Windows trata el mismo suceso como una access violation, con el código de excepción 0xC0000005.

Causas comunes de los segmentation faults

C y C++ permiten que un programa calcule cualquier dirección y la use, así que todas las causas se reducen a usar una dirección que no es válida.

  • Desreferenciar un puntero nulo. int *p = NULL; *p = 5; Una función que devuelve NULL cuando falla, como malloc o fopen, lleva aquí cuando no se comprueba su resultado.
  • Un índice mucho más allá del final de un array. C no comprueba los límites, así que arr[1000000] es simplemente una dirección un millón de elementos más adelante.
  • Usar memoria después de free. El puntero sigue guardando la dirección antigua, pero la memoria ya no te pertenece.
  • Un puntero sin inicializar. int *p; *p = 5; escribe a través del valor basura que tenga p en ese momento.
  • Desbordamiento de pila. Una función recursiva sin caso de parada sigue añadiendo marcos de pila hasta salirse del final de la pila. El ejemplo de abajo falló en macOS con Segmentation fault: 11 y código de salida 139.
  • Escribir en un literal de cadena. char *name = "coddy"; name[0] = 'C'; intenta cambiar memoria de solo lectura. En Linux eso es un segfault. En macOS el mismo programa se detuvo con Bus error: 10, una señal relacionada.
#include <stdio.h>

int depth(int n) {
    return depth(n + 1) + 1;   /* never stops calling itself */
}

int main(void) {
    printf("%d\n", depth(0));
    return 0;
}

Un fallo pequeño muchas veces no provoca ningún cierre, y eso lo hace más peligroso. Este bucle lee un elemento más allá del final de un array de tres elementos:

#include <stdio.h>

int main(void) {
    int scores[3] = {72, 88, 95};
    int total = 0;

    for (int i = 0; i <= 3; i++) {   /* <= reads scores[3] */
        total += scores[i];
    }
    printf("Total: %d\n", total);
    return 0;
}

Compilado con Clang en un Mac, imprimió Total: 256. El total correcto es 255. scores[3] eran los 4 bytes siguientes de la pila, que pertenecían al programa, así que no hubo fallo y el valor basura se sumó en silencio. El sistema operativo solo detiene los accesos a memoria que no pertenece en absoluto al programa.

La solución para ambos fallos es el mismo hábito: saber cuántos elementos hay y comprobar un puntero antes de seguirlo.

Best: 95
No scores, nothing to read

Qué significa "core dumped"

Un volcado de memoria (core dump) es un archivo que guarda una copia de la memoria del programa en el momento en que falló. Un depurador puede abrirlo después y mostrar exactamente dónde estaba el programa y qué contenían sus variables: gdb ./app core. En muchas distribuciones de Linux, systemd-coredump recoge estos archivos, y coredumpctl list los muestra. Cuando los volcados de memoria están desactivados, por ejemplo con ulimit -c 0, el mensaje es solo Segmentation fault, sin las palabras entre paréntesis.

Cómo encontrar la línea que falló

La línea donde el programa se cae muchas veces no es la línea que tiene el bug. Un puntero puede volverse inválido en una función y usarse en otra mucho después. Estas herramientas muestran ambas cosas.

Un depurador. Compila con información de depuración y ejecuta el programa dentro del depurador. Cuando se detenga, bt (backtrace) imprime la cadena de llamadas a funciones con nombres de archivo y números de línea. En Linux el depurador suele ser gdb; en macOS es lldb, donde bt funciona igual.

gcc -g app.c -o app
gdb ./app
(gdb) run
(gdb) bt

AddressSanitizer. Compila con -fsanitize=address (GCC y Clang lo admiten) y ejecuta el programa con normalidad. En lugar de un segfault sin más, imprime un informe que nombra el tipo de fallo, como heap-use-after-free o stack-buffer-overflow, con la línea que hizo el acceso y la línea que reservó la memoria. También detecta la lectura silenciosa de un elemento de más del ejemplo anterior, que por sí sola nunca provoca un cierre.

Valgrind. En Linux, valgrind ./app ejecuta un programa sin modificar y notifica cada lectura o escritura inválida, como Invalid read of size 4.

Segmentation faults en otros lenguajes

Python, Java y JavaScript comprueban cada índice y cada referencia antes de usarlos, así que los mismos fallos se convierten en excepciones con mensajes claros: IndexError o AttributeError en Python, ArrayIndexOutOfBoundsException o NullPointerException en Java, TypeError en JavaScript. Esas se pueden capturar con el manejo de excepciones. Un segfault no se puede manejar así: es una señal, y un bloque catch de C++ no la ve.

Los programas en Python aún pueden dar un segfault cuando falla el código C que tienen debajo. Esta línea le pide a ctypes que lea la dirección 0:

import ctypes
ctypes.string_at(0)

Ejecutado con python3 -X faulthandler, Python 3.12 imprimió Fatal Python error: Segmentation fault, seguido de las líneas de Python que se estaban ejecutando. El mismo fallo ocurre cuando una extensión en C o una biblioteca nativa tiene un bug de memoria. Rust sigue otro enfoque: su compilador rechaza, antes de construir el programa, la mayor parte del código que podría acceder a memoria inválida.

Qué leer después

La guía de C sobre segmentation faults repasa cada causa con un programa mínimo y su solución. Para evitar los fallos desde el principio, lee sobre punteros, punteros nulos y la pila y el heap, y después practícalos en el curso de C. Para ver cómo se notifican los errores en los lenguajes que comprueban la memoria por ti, consulta la página de error en tiempo de ejecución.

Preguntas frecuentes

¿Cómo se soluciona un segmentation fault?
Primero encuentra la línea: compila con -g y ejecuta el programa dentro de gdb o lldb, luego escribe bt tras el fallo, o compila con -fsanitize=address para obtener un informe detallado. Después corrige el puntero o el índice que usa esa línea: comprueba los punteros frente a NULL, mantén los índices de los arrays por debajo de la longitud, deja de usar la memoria después de free y asegúrate de que la recursión termina.
¿Un segmentation fault es una fuga de memoria?
No, son problemas opuestos. Una fuga de memoria es memoria que el programa reservó y nunca liberó, así que sigue ejecutándose mientras usa cada vez más memoria. Un segmentation fault es un acceso a memoria que no pertenece al programa, y el programa se detiene en el acto. Los fallos con free, como usar un puntero después de liberarlo, pueden causar segfaults, mientras que olvidar free causa fugas.
¿Por qué se llama segmentation fault?
El nombre viene de la segmentación de memoria, un diseño antiguo en el que la memoria de un programa se dividía en segmentos con límites fijos, y tocar una dirección fuera de tu segmento era un fallo. Los sistemas modernos gestionan la memoria en páginas, pero el nombre, y el de la señal SIGSEGV, se quedaron. Windows llama al mismo suceso access violation (infracción de acceso).
¿Python puede dar un segmentation fault?
El código Python normal no lo provoca, porque Python comprueba cada índice y cada referencia y lanza una excepción en su lugar. Aun así, un programa en Python puede dar un segfault dentro de código C: un módulo de extensión en C, una biblioteca como un framework de machine learning, o ctypes. Ejecutar python -X faulthandler script.py imprime las líneas de Python que se estaban ejecutando cuando falló.
¿Qué significa el código de salida 139?
El código de salida 139 significa que el proceso murió por la señal 11, que es SIGSEGV, un segmentation fault. Los shells notifican una muerte por señal como 128 más el número de la señal, y 128 + 11 = 139. En Docker y Kubernetes, un contenedor que termina con 139 tuvo un segfault en su proceso principal.
Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR