进/出调试器行为不同的程序


18

挑战在于编写确定性程序(任何语言/操作系统),该程序不带参数或其他输入,并且在调试器中的行为与未调试时的行为不同

例如,程序在调试时可能会输出某些内容,而在调试时可能不会输出任何内容。或在每种情况下输出不同的内容。否则可能在调试时崩溃,但在未调试时不会崩溃。或相反亦然。

注意事项和说明:

  • 时间差异不计算在内。
  • 允许翻译语言。
  • 为了强调确定性:在调试环境内外,行为都必须是完全可复制的。
  • 调试器本身的存在应该是两种情况之间的唯一区别。
    • 告诉调试器添加输入(stdin或argv ENV或其他)是作弊的,调试器应按原样运行程序。
    • 禁止在调试和非调试运行之间更改环境(例如,在虚拟机或其他操作系统中运行,或更改操作系统设置,例如内存限制)。

最短的代码胜出。我可能会颁发赏金,以揭示一些有关调试器如何工作的有趣信息。


4
一些调试器在启动时会向正常的编译器输出不同的文本,因此任何程序似乎都满足这些条件。这算吗?
小麦巫师

1
并非所有输出都来自调试器吗?如果我们要区分的话,对我来说不清楚是什么调试器输出还是程序输出。
小麦巫师

5
定义调试器?
Artemis

3
调试器是什么意思?哪一个?
MilkyWay90

6
您如何定义调试器?如果语言解释器支持“调试”模式(例如,引入了非标准命令),那算不算?
硕果累累

Answers:


31

Linux和OSX上的x86和x64_64机器语言,1个字节

0x0:  CC    int3 

在线尝试!

int 3抛出一个SIGTRAP将导致调试器停止,就好像遇到断点一样。在调试器之外,内核终止进程(感谢@Ruslan进行更正)。

C(gcc)(x86 Linux和OSX),14 11 9字节

main=204;

在线尝试!

整数204对应于int 3指令;TIO链接与上面相同。


1
C代码中的明确赋值,以前没有见过。
汤姆

4
实际上SIGTRAP不会产生SIGABRT,因此有关调用的部分abort()是错误的。根本就没有默认的信号处理程序SIGTRAP,因此内核终止了进程(父进程可以WIFSIGNALED用来检测该进程并WTERMSIG确定发生了哪个信号)。
Ruslan

9

APL(Dyalog Unicode),0字节

在Dyalog APL中,通过在IDE解释器或运行时解释器中运行工作区来选择调试器与不调试器。

将完全空的默认设置工作区加载到IDE解释器中,立即使用户进入REPL模式,因为应用程序必须主动关闭解释器才能退出:

IDE REPL

但是,运行时解释器没有REPL模式,因此,如果应用程序结束(例如,因为它完全为空)并且没有显式关闭解释器,则它暗中尝试进入REPL模式(“ APL会话”),并抱怨:

运行时对话框


9

Firefox上的JavaScript,69字节

警告:此脚本可能会挂起您的浏览器!请勿在其他浏览器(例如Chrome)上对其进行测试,因为它可能会使您的标签页/浏览器崩溃。

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

方法:在启用console选项卡的情况下启用调试器。console.log可能导致内存泄漏,并且程序很快会耗尽内存。禁用调试器后,GC将清除分配的内存,您最终将看到一条带有文本的警报1


8

MSVC(64位),50 35字节

main(){return IsDebuggerPresent();}

通常以代码0退出,但在调试器下以1退出(请注意,WinDbg不会自动显示退出代码,但您可以通过检查堆栈来伪造它)。编辑:由于@Ruslan,节省了15个字节。


1
MSVC是否需要原型?然后,您可能想在C89模式下尝试使用MinGW,以节省一些字节。
Ruslan

@Ruslan Bah,显示了我使用C语言以来已经有多长时间了
尼尔

7

T-SQL,6个字节

sp_who

调试器处于活动状态时,始终以执行用户的名称返回额外的一行。


5

Python,29个字节

import sys
sys.modules['pdb']

没有调试器(python3 /tmp/foo.py):

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

使用调试器(python3 -m pdb /tmp/foo.py):

(empty output)

因为pdb在第二种情况下已加载到应用程序可见的模块中。



4

Java 131102100字节

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

当不使用调试器运行时,此函数将返回一个长度为1的数组。当使用调试器运行时,此函数将返回一个长度为2(大于1)的数组。

在线尝试!

从技术上讲,这将检测您是否可以附加调试器。如果当前已连接,则为否...不确定是否有效

-23个字节,感谢OlivierGrégoire提到我可以减少我在运行时参数中搜索的内容并可以对我的答案进行lambda化

-5个字节,感谢Benjamin Urquhart指出,toString当我可以让Java隐式转换时,调用是愚蠢的

-2个字节,感谢Benjamin Urquhart更改了返回类型


3
您可以使用lambda缩短它。另外,您很有可能只能在上进行测试:jdwp,而不是-agentlib:jdwp。的:是区分runjdwp-agentlib:jdwp108字节
OlivierGrégoire


2
@BenjaminUrquhart我因错过toString这里的增强而感到愚蠢。接得好!

100字节 -当没有调试器处于活动状态时,返回长度为1的数组,如果可以有一个,则返回长度至少为2的数组。
本杰明·厄克特

3

Robotalk,22个字节

debug l: chronon l ifg

如果调试器处于活动状态,则该debug指令将暂停执行,直到当前游戏结束为止。在这种情况下,变量“ chronon”在读取时始终为1或更大,并且程序执行无限循环。如果调试器未处于活动状态,debug则为单周期无操作。读取时,“ Chronon”现在为0,不采用“ ifg”分支,并且执行到达代码的末尾,这是错误情况。


2

MATLAB,6个字节

dbquit

在调试器中停止时,这将退出调试模式。

当不在调试中时,它将打印一条错误消息,当未在调试器中停止时,该消息将无法使用。

应当注意,这仅适用于命令窗口中的评估(运行MATLAB代码的三种方式之一)。它无法在函数或脚本中运行,因为一旦您尝试运行脚本或函数,您将在执行过程中停止处于调试模式。

您也可以最接近将在函数/脚本中运行的内容:

MATLAB,22字节

feature('IsDebugMode')

这是MATLAB中未记录的命令。如果您停止在调试器中的脚本或函数中,然后调用包含上述行的另一个函数(或命令评估),它将返回true。

在调试器之外,它将返回false。

但是,如果您仅运行包含上述内容的脚本/函数,即使您在脚本/函数的开头添加断点并逐步执行,它也会返回false,因为再次执行后,您将停止在临时调试器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.