>_cmd.script

ctrace

Historical C program execution tracer (obsolete, superseded by gdb/strace/ltrace)

Development

By CMD Script Team · 4 min read · Last updated

SYNTAX
ctrace [OPTIONS] FILE.c

Options

Command options and flags
FlagDescription
-o FILEWrite the instrumented, trace-annotated source to FILE
-f FUNCTIONLimit tracing output to a specific function, where supported
-lInclude line-number annotations in the trace output
-vVerbose 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 of program.c that 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 program
  • strace ./program — trace every system call the program makes
  • ltrace ./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 ./program then use break, next, step, and print.
  • Modern equivalent for tracing external interactions without source access: strace -f -e trace=open,read,write ./program
  • Combine gdb with 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 ctrace on a modern system and finding it isn't packaged anywhere — treat any reference to it in old documentation as a sign to reach for gdb, strace, or ltrace instead.
  • 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 ctrace mentioned in old build scripts or documentation, treat it purely as historical context — replace the workflow with gdb for interactive debugging or strace/ltrace for call tracing.
  • strace -f follows 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 gdb for interactive, source-level debugging needs where you want to inspect state at specific points in the code.
  • Use strace/ltrace when 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.