18
\$\begingroup\$

The challenge is to write a deterministic program (any language/OS) which takes no arguments or other input and behaves differently in a debugger from how it behaves when not being debugged.

For example, the program may output something when being debugged but not output anything when not being debugged. Or output something different in each case. Or it may crash when being debugged but not crash when not being debugged. Or vice-versa.

Caveats and clarifications:

  • Timing differences do not count.
  • Interpreted languages are permitted.
  • To emphasize determinism: the behaviour must be exactly reproducible both in and out of debugging context.
  • The presence of the debugger itself should the only difference between the two cases.
    • Telling the debugger to add inputs (stdin or argv ENV or whatever) is cheating, the debugger should run the program "as-is".
    • Changing the environment (e.g. running in a virtual machine or different OS, or changing OS settings such as memory limits) between debug and non-debug runs is not permitted.

Shortest code wins. I may award a bounty which reveals something interesting about how debuggers work.

\$\endgroup\$
9
  • 4
    \$\begingroup\$ Some debuggers output different text on startup to the normal compiler, thus any program seems to meet these conditions. Does that count? \$\endgroup\$
    – Wheat Wizard
    May 12, 2019 at 14:48
  • 1
    \$\begingroup\$ Doesn't all output come from the debugger? It's not clear to me what debugger output is vs. program output if we are making a distinction. \$\endgroup\$
    – Wheat Wizard
    May 12, 2019 at 15:42
  • 5
    \$\begingroup\$ Define debugger? \$\endgroup\$
    – Miriam
    May 12, 2019 at 19:05
  • 3
    \$\begingroup\$ What do you mean by debugger? Which one? \$\endgroup\$
    – MilkyWay90
    May 12, 2019 at 23:43
  • 6
    \$\begingroup\$ How do you define a debugger? If a language interpreter supports a "debug" mode (which, say, introduces nonstandard commands), does that count? \$\endgroup\$ May 13, 2019 at 0:24

10 Answers 10

31
\$\begingroup\$

x86 and x64_64 machine language on Linux and OSX, 1 byte

0x0:  CC    int3 

Try it online!

int 3 throws a SIGTRAP which will cause a debugger to stop as if it encountered a breakpoint. Outside of a debugger, the kernel terminates the process (thanks to @Ruslan for the correction).

C (gcc) (x86 Linux and OSX), 14 11 9 bytes

main=204;

Try it online!

The integer 204 corresponds to the int 3 instruction; the TIO link is the same as above.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ clear assignment in the C code, haven't seen that before. \$\endgroup\$
    – Tom
    May 13, 2019 at 9:18
  • 4
    \$\begingroup\$ Actually SIGTRAP doesn't result in SIGABRT, so the part about calling abort() is wrong. There's simply no default signal handler for SIGTRAP, so the kernel terminates the process (and the parent can use WIFSIGNALED to detect this and WTERMSIG to determine which signal happened). \$\endgroup\$
    – Ruslan
    May 13, 2019 at 16:02
10
\$\begingroup\$

APL (Dyalog Unicode), 0 bytes

In Dyalog APL, debugger vs no debugger is choosen by running one's workspace in either the IDE interpreter or the runtime interpreter.

Loading a completely empty default settings workspace into the IDE interpreter, immediately drops the user into REPL mode as applications must actively shut down the interpreter for it to quit:

IDE REPL

However, the runtime interpreter does not have a REPL mode, and so if an application comes to an end (for example because it is completely empty) and does not explicitly shut down the interpreter, it implicitly has attempted to reach REPL mode ("the APL session"), and complains:

Runtime dialog

\$\endgroup\$
9
\$\begingroup\$

JavaScript on Firefox, 69 bytes

WARNING: This script may hang your browser! Do NOT test it with other browsers (e.g. Chrome) as it may crash your tab / browser.

for(console.log(a={},i=99);--i;a=a.a={k:new Int8Array(1e9)});alert(1)

How: When debugger is enabled with console tab activated. console.log makes memory leak possible, and the program will run out of memory soon. When debugger is disabled, GC would clear memory allocated, and you would see an alert with text 1 finally.

\$\endgroup\$
8
\$\begingroup\$

MSVC (64-bit), 50 35 bytes

main(){return IsDebuggerPresent();}

Exits with code 0 normally but 1 under the debugger (note that WinDbg does not automatically display the exit code but you can fake it by examining the stack). Edit: Saved 15 bytes thanks to @Ruslan.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Does MSVC require prototypes? You might then want to try with MinGW in C89 mode, to save some bytes. \$\endgroup\$
    – Ruslan
    May 13, 2019 at 16:16
  • \$\begingroup\$ @Ruslan Bah, shows how long it's been since I've used C... \$\endgroup\$
    – Neil
    May 13, 2019 at 20:16
7
\$\begingroup\$

T-SQL, 6 bytes

sp_who

Always returns an extra row under the executing user's name when the debugger is active.

\$\endgroup\$
5
\$\begingroup\$

Python, 29 bytes

import sys
sys.modules['pdb']

Without debugger (python3 /tmp/foo.py):

Traceback (most recent call last):
  File "/tmp/foo.py", line 2, in <module>
    sys.modules['pdb']
KeyError: 'pdb'

With debugger (python3 -m pdb /tmp/foo.py):

(empty output)

because pdb is loaded into an app-visible module in the second case.

\$\endgroup\$
4
\$\begingroup\$

JavaScript, 17 bytes

debugger
alert(1)

debugger stops execution if the debugger console is open, else it does nothing

\$\endgroup\$
4
\$\begingroup\$

Java, 131 102 100 bytes

v->(java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments()+"").split(":jdwp")

When running without a debugger this function returns an array of length 1. When running with a debugger, this returns an array of length 2 (greater than 1).

Try it online!

This technically detects if you could attach a debugger; not if one is currently connected... Not sure if that's valid

-23 bytes thanks to Olivier Grégoire for mentioning that I can cut down on what I search for in the runtime parameters and for lambda-izing my answer

-5 bytes thanks to Benjamin Urquhart for noting that calling toString is dumb when I can let Java implicitly convert

-2 bytes thanks to Benjamin Urquhart for changing the return type

\$\endgroup\$
4
  • 3
    \$\begingroup\$ You can shorten it using a lambda. Also, it's very likely that you can test only on :jdwp, instead of -agentlib:jdwp. The : is to distinguish runjdwp from -agentlib:jdwp. 108 bytes \$\endgroup\$ May 13, 2019 at 12:09
  • 2
    \$\begingroup\$ 103 bytes \$\endgroup\$ May 13, 2019 at 13:00
  • 2
    \$\begingroup\$ @BenjaminUrquhart I feel dumb for missing the toString enhancement here. Good catch! \$\endgroup\$
    – Poke
    May 13, 2019 at 15:08
  • \$\begingroup\$ 100 bytes - returns array of length 1 when no debugger is active, array of length at least 2 if there can be one. \$\endgroup\$ May 26, 2019 at 4:36
3
\$\begingroup\$

Robotalk, 22 bytes

debug l: chronon l ifg

If the debugger is active, the debug instruction pauses execution until the end of the current game tick. In this case, the variable "chronon" is always 1 or greater when read, and the program executes an infinite loop. If the debugger isn't active, debug is a one-cycle no-op. "Chronon" is now 0 when read, the "ifg" branch isn't taken, and execution reaches the end of the code, which is an error condition.

\$\endgroup\$
2
\$\begingroup\$

MATLAB, 6 bytes

dbquit

When stopped in the debugger, this will quit debugging mode.

When not under debug, it will print an error message that it cannot be used when not stopped in the debugger.

It should be noted this only works for evaluation in the command window (one of the three ways of running MATLAB code). It won't work in a function or script as once you try to run the script or function, you stop being in debug mode during execution.

The closest you can get to something that will run in a function/script as well would be:

MATLAB, 22 bytes

feature('IsDebugMode')

This is an undocumented command in MATLAB. If you are stopped in the debugger in a script or function, and then call another function (or command evaluation) that contains the above line, it will return true.

Outside the debugger it will return false.

If you were however to just run a script/function containing the above, even if you add a breakpoint at the start of the script/function and step through, it will return false, because again, once you start executing you stop being in the debugger temporarily.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.