ctrace
Historical C program execution tracer (obsolete, superseded by gdb/strace/ltrace)
By CMD Script Team · 4 min read · Last updated
ctrace [OPTIONS] FILE.cOptions
| Flag | Description |
|---|---|
-o FILE | Write the instrumented, trace-annotated source to FILE |
-f FUNCTION | Limit tracing output to a specific function, where supported |
-l | Include line-number annotations in the trace output |
-v | Verbose mode, printing additional detail about each traced statement |
Distribution compatibility
- Not installed by default on Ubuntu/Debian
- Not installed by default on Fedora/Arch
- Not available on macOS
What it does
ctrace was a historical C program execution tracer: it worked by instrumenting C
source code, inserting statements that printed each executed line and relevant variable
values as the program ran, then compiling and running that instrumented version. This
gave developers a crude but useful trace of control flow and state without a full
interactive debugger. It is obsolete today — it is not packaged on any current
mainstream Linux distribution or on macOS, and its role has been fully absorbed by
modern tools: gdb for interactive source-level debugging, and strace/ltrace for
tracing system calls and library calls on a running process without needing to modify or
recompile source.
Beginner examples
ctrace -o traced.c program.c— historical usage: produce an instrumented copy ofprogram.cthat prints a trace when compiled and run- Because ctrace is essentially unavailable today, the realistic "beginner" step is learning its modern replacements instead:
gdb ./program— start an interactive debugger session on a compiled programstrace ./program— trace every system call the program makesltrace ./program— trace every dynamic library call the program makes
gdb ./program
Advanced examples
- Historical ctrace-style workflow: instrument, compile, and run the traced source to get a line-by-line execution log, then manually inspect the printed trace for the bug.
- Modern equivalent for the same goal — stepping through logic interactively without
modifying source:
gdb -q ./programthen usebreak,next,step, andprint. - Modern equivalent for tracing external interactions without source access:
strace -f -e trace=open,read,write ./program - Combine
gdbwith core dumps for postmortem debugging instead of live instrumentation:gdb ./program core
strace -f -e trace=network ./program
Common mistakes
- Trying to install or locate
ctraceon a modern system and finding it isn't packaged anywhere — treat any reference to it in old documentation as a sign to reach forgdb,strace, orltraceinstead. - Assuming a source-instrumentation tracer like ctrace could trace binaries you don't
have source for — it fundamentally required recompiling instrumented source, unlike
strace/ltrace, which attach to already-compiled processes. - Confusing execution tracing (what ctrace, strace, and gdb all do in different ways) with static analysis — none of these tools find bugs without actually running the program.
Tips
- If you find
ctracementioned in old build scripts or documentation, treat it purely as historical context — replace the workflow withgdbfor interactive debugging orstrace/ltracefor call tracing. strace -ffollows child processes as well, which is useful when debugging a program that forks — something source-instrumentation tracers like ctrace couldn't easily do.- Use
gdb's scripting support (.gdbinit, Python scripting) for the kind of conditional, targeted tracing that older tools like ctrace approximated manually.
Best practices
- Use
gdbfor interactive, source-level debugging needs where you want to inspect state at specific points in the code. - Use
strace/ltracewhen you need to observe a program's interaction with the OS or libraries without recompiling or modifying its source. - Don't attempt to resurrect or depend on ctrace for new work — its function is fully covered, and better served, by modern tooling.
Try it yourself
A simulated shell with a sample home directory — experiment freely, nothing leaves your browser. Type help to list supported commands.
Real-world use cases
- Historical/archival context: understanding how developers traced program execution before mature interactive debuggers were common.
- Modernizing an old build pipeline that references ctrace by replacing the debugging step with gdb or strace-based workflows.
- Teaching the evolution of C debugging tools when explaining why strace/ltrace/gdb are the current standard.
Common interview questions
- Is ctrace still used in modern development? No — it's an obsolete source instrumentation tracer, superseded by gdb for interactive debugging and strace/ltrace for call tracing; it isn't packaged on current distributions.
- How did ctrace's technique differ from strace's? ctrace instrumented and recompiled the actual C source to print execution traces, requiring source access and a rebuild; strace instead attaches to an already-running or newly-launched process and intercepts system calls at the kernel boundary, needing no source changes.
- What would you use today instead of ctrace? gdb for interactive, source-level debugging (breakpoints, stepping, variable inspection), and strace or ltrace for tracing system calls or library calls on a compiled binary without modifying it.
Frequently Asked Questions
Is ctrace still used today?
No. ctrace was a source-level C execution tracer from an earlier era of Unix development, working by instrumenting source code to print each executed statement and variable value. It's obsolete and not packaged on any current mainstream Linux distribution or macOS.
What replaced ctrace?
gdb (the GNU Debugger) is the standard interactive source-level debugger today, letting you set breakpoints, step through code, and inspect variables without modifying source. strace and ltrace trace system calls and library calls respectively at the process level, which covers much of what execution tracers like ctrace were used for, without needing to instrument or recompile source.
How did ctrace's approach differ from strace?
ctrace worked by instrumenting the C source itself (effectively inserting print statements at each line/statement) before compiling, so it required source access and a rebuild. strace instead attaches to a running process and intercepts system calls at the kernel boundary, requiring no source changes or recompilation, which is a large part of why it displaced source-instrumentation tracers.
Cheat sheet
Download a quick-reference cheat sheet for ctrace.