Question

Finding Core Dump Files in C on Linux

clinuxcoredump

Question

While running a C program on Linux, the shell prints (core dumped), but no core file appears in the current directory. The core-size limit has been set and verified:

ulimit -c unlimited
ulimit -a

Searching for a file named core also finds nothing. Where is the core dump file, and what settings determine its location?

Short Answer

A core dump is a snapshot of a process when it crashes. Setting ulimit -c unlimited allows a dump to be created, but it does not guarantee that a file named core will be written to the current directory. On Linux, the kernel's core_pattern setting can choose the filename, redirect the dump to another directory, or send it to a crash-reporting service such as systemd-coredump.

Concept

A core dump is a file containing information about a program at the time it terminated unexpectedly, such as after a segmentation fault. Debuggers such as GDB can combine the core dump with the program executable and its debug symbols to inspect the crash.

The message (core dumped) generally means the process ended from a signal for which the system attempted to produce a core dump. It does not mean that a file called core was successfully placed in your current directory.

On Linux, core-dump behavior is controlled by several layers:

  • Resource limit: ulimit -c controls the maximum permitted size of a core dump for processes started by that shell.
  • Kernel naming and destination rule: /proc/sys/kernel/core_pattern determines the dump's filename, destination, or handler.
  • Crash handler: If core_pattern starts with |, the kernel sends dump data to a program instead of writing a normal file. A common example is systemd-coredump.
  • Process and filesystem conditions: The process must be allowed to dump core, and the destination must be usable and have enough storage.

Check the active Linux core-dump rule with:

cat /proc/sys/kernel/core_pattern

Possible results include:

core

This usually writes a file named core in the crashing process's current working directory.

core.%p

This writes a name such as core.12345, where %p is the process ID.

/var/crash/core.%e.%p

This writes elsewhere, not in the current directory. %e represents the executable name.

|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

This pipes the dump to systemd-coredump; there may be no ordinary core file in your directory.

If systemd handles core dumps, inspect them with:

coredumpctl list
coredumpctl info

To debug the most recent recorded dump:

coredumpctl debug

Core dumps can contain passwords, private application data, and memory from other libraries. Treat them as sensitive files.

Mental Model

Think of a core dump as a crash report package.

  • ulimit -c unlimited is permission to create a package with no size cap.
  • core_pattern is the shipping label: it says what the package is called and where it goes.
  • A | at the beginning of core_pattern means a courier service receives the package instead of leaving it at your door.

Therefore, allowing packages to be sent does not mean one will appear on your desk—the delivery rule may send it to a central crash-reporting office.

Take Quiz

Syntax and Examples

On Linux, first inspect the settings that most directly affect core dumps:

# Maximum core-dump size for this shell and its child processes
ulimit -c

# Kernel rule for core-dump names and destinations
cat /proc/sys/kernel/core_pattern

# Whether the current shell is allowed to create core dumps
cat /proc/$$/limits | grep -i 'core file size'

A small C program that deliberately crashes can be used for testing:

#include <stdio.h>

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

    puts("About to crash");
    *number = 42;  // Invalid write: typically causes SIGSEGV.

    return 0;
}

Compile and run it:

gcc -g -O0 -o crash crash.c
ulimit -c unlimited
./crash

The -g option includes debugging information, and -O0 avoids optimization so debugger output is easier for beginners to follow.

If core_pattern produces a local file, find likely names in the current directory:

ls -lah core core.* 2>/dev/null

Do not search only for the exact name core: patterns often add the executable name, process ID, timestamp, signal number, or other fields.

Step by Step Execution

Use this test program:

#include <stdio.h>

int main(void) {
    int *pointer = NULL;
    puts("Starting");
    *pointer = 10;
    puts("Finished");
    return 0;
}

Execution proceeds as follows:

  1. pointer is assigned NULL, meaning it does not point to valid writable memory.
  2. puts("Starting") prints Starting.
  3. *pointer = 10 tries to write through a null pointer.
  4. The operating system normally sends the process SIGSEGV (segmentation fault).
  5. The process terminates. The final puts line is never reached.
  6. Linux checks whether the process may create a core dump, including its core-size limit.
  7. Linux applies the rule in /proc/sys/kernel/core_pattern.
  8. The result may be a file in the current directory, a file elsewhere, a record managed by systemd-coredump, or no stored dump if another condition prevents it.

If a local core file is created, inspect it with GDB:

gdb ./crash ./core

The exact core filename may differ. In GDB, run:

bt

bt means “backtrace”; it shows the function-call stack at the crash.

Real World Use Cases

Core dumps are useful when a failure cannot be reproduced easily or when it occurs outside an interactive development environment.

  • Production service crash: A backend process crashes under a rare request pattern. Engineers inspect the saved dump to see the failing stack frame and variable values.
  • Native extension failure: A Python, Node.js, Java, or database process crashes because a C or C++ extension has invalid memory access.
  • Embedded or device software: Logs may only show that a process died. A core dump can preserve the program state needed to diagnose the issue.
  • CI test failure: A native test binary crashes in an automated job. The job uploads the core dump as a protected build artifact.
  • Memory-corruption investigation: A program may crash long after the original bug. The dump helps locate where invalid data was eventually used.

Because dumps may expose secrets and user data, production systems often store them centrally with restricted access or disable them entirely.

Take Quiz

Real Codebase Usage

In real projects, developers usually make core dumps part of a deliberate debugging workflow rather than relying on a file in the working directory.

Run a debug build

gcc -g -O0 -Wall -Wextra -o app app.c
ulimit -c unlimited
./app

Debug symbols make stack traces useful. Without them, GDB may show raw addresses or incomplete function information.

Inspect the configured destination

cat /proc/sys/kernel/core_pattern

If the output begins with |, use the configured crash-service tooling. With systemd this is commonly:

coredumpctl list
coredumpctl info <PID-or-EXE>
coredumpctl debug <PID-or-EXE>

Use a controlled filename during local debugging

On a development machine, an administrator can configure a pattern such as:

/var/tmp/core.%e.%p

This avoids overwriting one dump with another and keeps crash files out of source directories. Changing /proc/sys/kernel/core_pattern generally requires administrative privileges and may be managed by system configuration tools.

Combine prevention and diagnosis

Core dumps diagnose a crash after it happens. Teams also use compiler warnings and runtime tools to catch memory bugs earlier:

gcc -g -O0 -Wall -Wextra -fsanitize=address -o app app.c
./app

AddressSanitizer often reports an invalid memory access close to its cause, while a core dump is especially valuable for crashes that happen in a deployed environment.

Common Mistakes

Assuming (core dumped) guarantees a local file

The message does not promise ./core. Check the system rule:

cat /proc/sys/kernel/core_pattern

If it starts with |, a handler receives the dump instead of the current directory.

Searching only for core

This can miss files named core.1234, core.myapp.1234, or files stored in another directory.

# Better for a local current-directory pattern
ls -lah core* 2>/dev/null

Always inspect core_pattern before guessing the name or location.

Setting ulimit in the wrong shell

This affects processes started after the command, and only descendants of that shell.

ulimit -c unlimited
./my_program

If a service manager starts the program, changing your interactive shell's limit may not affect the service. Configure the relevant service or runtime environment instead.

Ignoring permissions, storage, and filesystem restrictions

A normal file cannot be written when the target directory is unavailable, not writable, full, read-only, or otherwise restricted. A system crash handler can also have its own retention and size policies.

Expecting a core dump for every failure

A program can exit normally, call exit, be killed with a non-core-producing signal, or be configured as non-dumpable. Not every termination creates a dump.

Compiling without debug symbols

This compiles successfully but makes debugging much harder:

gcc -o app app.c

Prefer a debug build while investigating:

gcc -g -O0 -o app app.c

Comparisons

MechanismWhat it controlsTypical checkImportant detail
ulimit -cMaximum permitted core-dump sizeulimit -cIt permits or limits dumps; it does not choose the location.
core_patternFilename, destination, or handlercat /proc/sys/kernel/core_patternIt may create names other than core or pipe data to a program.
Current directoryDefault location for some patternspwdRelevant only when the pattern is a relative filename such as core.
systemd-coredumpCentral collection and storage of dumpscoredumpctl listDumps may be stored in the journal or a system directory rather than beside the executable.
GDBAnalysis of an executable and core dumpgdb ./app ./core-fileGDB reads dumps; it does not determine where Linux stores them.

A relative pattern such as core.%p is different from an absolute pattern such as /var/tmp/core.%p:

  • A relative pattern is generally created relative to the crashing process's working directory.
  • An absolute pattern specifies a fixed destination directory.
  • A pattern beginning with | invokes a handler program rather than directly writing the dump as a normal file.
Take Quiz

Cheat Sheet

# Permit unlimited-size core dumps for programs started from this shell
ulimit -c unlimited

# Display the limit
ulimit -c

# Display Linux's core-dump naming/destination rule
cat /proc/sys/kernel/core_pattern

# Check the current shell's inherited core-size limit
cat /proc/$$/limits | grep -i 'core file size'

# Look for common local dump names
ls -lah core* 2>/dev/null

# On systems using systemd-coredump
coredumpctl list
coredumpctl info
coredumpctl debug

# Build a C program for debugging
gcc -g -O0 -Wall -Wextra -o app app.c

# Open a local dump in GDB
gdb ./app ./core-file

Key rules:

  • ulimit -c controls the allowed size, not the path.
  • Read core_pattern to learn the actual naming and delivery behavior.
  • %p in a pattern represents a process ID; patterns can therefore create core.12345 instead of core.
  • A core_pattern beginning with | sends dump data to a handler such as systemd-coredump.
  • Build with -g before a crash if you want useful source-level debugging.

FAQ

Why does Linux say “core dumped” but no core file exists?

The dump may use a different name, be written to another directory, or be captured by a service such as systemd-coredump. Check /proc/sys/kernel/core_pattern.

Does ulimit -c unlimited choose where the core dump goes?

No. It sets the maximum core-dump size for processes started by that shell. The kernel's core_pattern setting determines the destination and naming behavior.

How do I find a core dump managed by systemd?

Use:

coredumpctl list
coredumpctl info

Then use coredumpctl debug to open a recorded dump in GDB when available.

Why is my dump named core.12345 instead of core?

The active core_pattern likely includes %p, which expands to the process ID. This prevents multiple crashes from overwriting the same file.

Why did changing ulimit not affect my application service?

A service is often started by systemd or another supervisor, not by your current shell. It has its own resource-limit configuration.

Can I always change core_pattern myself?

Usually no. It is a system-wide kernel setting and generally requires administrator privileges. On managed systems, change it through the system's configuration mechanism rather than modifying it temporarily.

Are core dumps safe to share?

Not necessarily. They may contain credentials, tokens, private user data, or proprietary application state. Store and share them only through approved, access-controlled channels.

Take Quiz

Mini Project

Description

Create a small C crash-test program and a shell-based inspection workflow. The project demonstrates that a core dump's permitted size, filename, and destination are separate concerns, and it gives you commands to identify where a Linux system records crashes.

Goal

Build a debug-friendly C program that intentionally crashes, then determine whether Linux created a local core file or recorded it through systemd.

Requirements

Compile the program with debug symbols and warnings enabled.

Set the core-size limit to unlimited in the shell that starts the program.

Print the active core_pattern before running the test.

Cause a deliberate segmentation fault.

Check both for local core* files and for systemd-managed dumps when coredumpctl is available.

Take Quiz

Keep learning

Related questions

View more