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 -ccontrols the maximum permitted size of a core dump for processes started by that shell. - Kernel naming and destination rule:
/proc/sys/kernel/core_patterndetermines the dump's filename, destination, or handler. - Crash handler: If
core_patternstarts with|, the kernel sends dump data to a program instead of writing a normal file. A common example issystemd-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 unlimitedis permission to create a package with no size cap.core_patternis the shipping label: it says what the package is called and where it goes.- A
|at the beginning ofcore_patternmeans 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.
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:
pointeris assignedNULL, meaning it does not point to valid writable memory.puts("Starting")printsStarting.*pointer = 10tries to write through a null pointer.- The operating system normally sends the process
SIGSEGV(segmentation fault). - The process terminates. The final
putsline is never reached. - Linux checks whether the process may create a core dump, including its core-size limit.
- Linux applies the rule in
/proc/sys/kernel/core_pattern. - 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.
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
| Mechanism | What it controls | Typical check | Important detail |
|---|---|---|---|
ulimit -c | Maximum permitted core-dump size | ulimit -c | It permits or limits dumps; it does not choose the location. |
core_pattern | Filename, destination, or handler | cat /proc/sys/kernel/core_pattern | It may create names other than core or pipe data to a program. |
| Current directory | Default location for some patterns | pwd | Relevant only when the pattern is a relative filename such as core. |
systemd-coredump | Central collection and storage of dumps | coredumpctl list | Dumps may be stored in the journal or a system directory rather than beside the executable. |
| GDB | Analysis of an executable and core dump | gdb ./app ./core-file | GDB 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.
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 -ccontrols the allowed size, not the path.- Read
core_patternto learn the actual naming and delivery behavior. %pin a pattern represents a process ID; patterns can therefore createcore.12345instead ofcore.- A
core_patternbeginning with|sends dump data to a handler such assystemd-coredump. - Build with
-gbefore 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.
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.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.