Segmentation fault (core dumped) (tested)

Segmentation fault means your program touched memory it isn't allowed to touch, and the kernel killed it with SIGSEGV. The optional (core dumped) suffix just means the shell also wrote a core file. We reproduced both the crash and the suffix on a real box to show exactly when each appears.

1. What actually happens

A segmentation fault is the kernel stopping a process that tried to read or write memory it doesn't own, most often through a null or wild pointer. The kernel sends the process signal 11 (SIGSEGV). The process usually has no handler for it, so it dies, and the shell that started it prints a message.

We wrote this minimal C program:

#include <stdio.h>
int main(void) {
    int *p = NULL;
    printf("before crash\n");
    fflush(stdout);
    *p = 42;
    printf("never gets here\n");
    return 0;
}

Compiled with gcc -O0 -g -o segfault segfault.c on gcc 14.2.0, no warnings. Writing through p dereferences a null pointer, which is unmapped memory, so the kernel delivers SIGSEGV.

2. The exact shell output we measured

Running the compiled binary under bash gave:

$ ./segfault
before crash
Segmentation fault      (core dumped)
$ echo $?
139

With core dumps disabled (ulimit -c 0, the box's default) the same crash printed:

$ ulimit -c 0
$ ./segfault
before crash
Segmentation fault
$ echo $?
139

Only the trailing (core dumped) changes. The job-control line bash shows ([1]+ Segmentation fault (core dumped) ./segfault) also includes a job number and PID when the process is backgrounded; in a plain foreground run bash just prints Segmentation fault with or without the suffix. We confirmed the same two outputs under dash (Debian's /bin/sh), so this is shell-independent: it's controlled by the resource limit, not the shell.

Exit code was 139 in every run. That is the standard 128 + signal number convention: 128 + 11 (SIGSEGV) = 139. This is how scripts and CI detect a segfault reliably, since the text message can vary by shell and locale but the exit code does not.

3. What controls "(core dumped)"

The suffix appears only if two things are both true: the process's core resource limit allows a dump, and the kernel successfully wrote one. We tested both settings in the same shell session:

SettingCommandShell outputCore file written?
Disabled (box default)ulimit -c 0Segmentation faultNo
Enabledulimit -c unlimitedSegmentation fault (core dumped)Yes, 438272 bytes

We checked ulimit -c before changing anything: it was 0 by default on this box, which is why most interactive shells only ever show the plain Segmentation fault message unless something has raised the limit.

After ulimit -c unlimited, the crash left a real file named core.<pid> (for example core.2098362) in the current directory. That naming and location come from /proc/sys/kernel/core_pattern, which on this box was the plain default core (pattern core.%p is common too; check your own box, don't assume). file core.2098362 confirmed it: ELF 64-bit LSB core file, x86-64 ... from './segfault'.

Some distros point core_pattern at systemd-coredump instead of a plain file (a line starting with | and a path like /usr/lib/systemd/systemd-coredump). This box does not: core_pattern was the literal string core, and the coredumpctl command was not installed, so dumps land as ordinary files you inspect with gdb or file directly, not through coredumpctl.

4. Reproduce it yourself

cat > segfault.c <<'EOF'
int main(void) { int *p = 0; *p = 1; return 0; }
EOF
gcc -O0 -g -o segfault segfault.c
ulimit -c unlimited   # enable core dumps for this shell
./segfault
echo $?                # 139
ls core.*               # the dump, if core_pattern writes plain files

If you have gdb installed, open the dump with gdb ./segfault core.<pid> and run bt for a backtrace showing the crashing line. On systems that route dumps to systemd, use coredumpctl list and coredumpctl debug instead of a bare filename.

5. Common real causes

6. How to actually debug one

Frequently asked questions

What does "Segmentation fault (core dumped)" actually mean?

The kernel killed your process with SIGSEGV because it accessed memory it wasn't allowed to. "(core dumped)" just means a memory snapshot (a core file) was also written, which only happens if ulimit -c allows it. We measured both: the fault text is identical either way, only the suffix changes.

Why don't I see "(core dumped)" on my machine?

Because your shell's core size limit is 0 by default, which is what we found on this Debian 13 box with ulimit -c. Run ulimit -c unlimited first, then reproduce the crash, and the suffix appears along with an actual core.<pid> file.

What exit code does a segfault produce?

139, which we confirmed in every run. That's 128 + 11, where 11 is SIGSEGV's signal number. Checking for 139 in scripts is more reliable than matching the printed text, since the text varies by shell.

Where does the core file go?

Wherever /proc/sys/kernel/core_pattern says. We found the plain pattern "core" on this box, so files appeared as core.<pid> in the working directory. Some distros instead pipe dumps to systemd-coredump, in which case you list and inspect them with coredumpctl rather than looking for a file.

Does the shell matter, e.g. bash vs sh?

No. We reproduced the identical pair of outputs, Segmentation fault and Segmentation fault (core dumped), under both bash and dash (Debian's /bin/sh). The deciding factor is the process's core resource limit, not which shell launched it.

Written with AI assistance. Measured on 2026-10-02 on Debian GNU/Linux 13 (trixie), gcc 14.2.0, bash 5.x and dash, kernel 6.12.107+deb13-amd64. Compiled a tiny C program with a null-pointer write and ran it under both ulimit -c 0 and ulimit -c unlimited. PlainHeaders is our extension; gcc, bash and dash are free.