[HN Gopher] 16 bytes of Python that compile to 32 terabytes of b...
___________________________________________________________________
16 bytes of Python that compile to 32 terabytes of bytecode (2016)
Author : azhenley
Score : 131 points
Date : 2021-02-16 19:22 UTC (3 hours ago)
(HTM) web link (codegolf.stackexchange.com)
(TXT) w3m dump (codegolf.stackexchange.com)
| [deleted]
| tylerhou wrote:
| Someone asked (and deleted their comment while I was writing my
| reply):
|
| > How does this compile in another language such as C?
|
| It doesn't; the C language doesn't implement arbitrary size
| integers, and therefore most C compilers won't fold constants of
| such large size.
|
| If you used a library that provided BigInts (arbitrary size
| integers), and and the library also provided a compiler extension
| to fold BigInt expressions at compile time, then you would likely
| get a large executable as well (most of the size would come from
| the data section).
| falcolas wrote:
| Well, you could probably abuse preprocessor macros and make
| something similar in C.
| azhenley wrote:
| I can't find my favorite C macro bomb, but this same post has
| a C answer using defines:
| https://codegolf.stackexchange.com/a/69413/4270
|
| The C++ template answers are particularly scary...
| shakna wrote:
| Not entirely of the same vein, but this C++ stacktrace bomb
| is one of my favourites: struct x struct z<
| x(x(x(x(x(x(x(x(x(x(x(x(x(x(x(x(x(y,x(y><y*,x(y*w>v<y*,w,x{}
|
| A tiny 79 bytes that explodes into a huge stacktrace that
| takes an inordinate amount of time to finish processing.
| colejohnson66 wrote:
| How is this supposed to work?
| phoe-krk wrote:
| Try compiling it. The compiler will scream at you for a
| _long_ long time.
|
| Also see https://codegolf.stackexchange.com/questions/195
| 6/generate-t...
| colejohnson66 wrote:
| Ah. I was confused by your usage of the word "stacktrace"
| which, to me, means an exception stack trace, not an
| error message. For those curious: $ g++
| test.cpp 2>&1 > /dev/null | wc -l 10223622
|
| _Ten million lines._
| phoe-krk wrote:
| Wasn't "my" usage per se since I'm not the original
| comment author, but yes, I too find this term confusing
| in this context. A stack trace to me usually means a
| textual dump of a call stack printed from some point of
| the program execution (usually an error site and/or a
| breakpoint), not compiler output that contains no
| information about the compiler's runtime stack.
| Sharlin wrote:
| In this case the error message contains information about
| the compiler's _template instantiation stack_ which is
| rather analogous to the stack trace of a recursive
| function. But yeah, a somewhat nonstandard usage.
| gpderetta wrote:
| I would say that 'stacktrace' is appropriate.
|
| The template expansion machinery is pretty much a purely
| functional language and the compiler is the interpreter.
| The stacktrace in this case is not of the interpreter
| itself but of the program being executed.
|
| In fact understanding that template error messages are
| none other than execution stack traces is key to
| understanding them.
| Karliss wrote:
| Even without abusing preprocessor or C++ templates you do
| something as simple as global array char a[1ULL<<30]={1};
|
| Initialize at least one member so that it gets placed in data
| section instead of bss resulting in binary size more or less
| the same as array. Although at least on my system various
| parts of toolchain start to break down once you reach 2GB
| limit.
| shakna wrote:
| The plain C equivalent to the above, changing the "command"
| part to be something valid: const
| main[255<<21]={195};
|
| You can also get around the 2Gb limit by using the -mcmodel
| flag, such as 'gcc -mcmodel=medium FILE'. But then actually
| compiling the thing takes a long time and a heck of a lot
| of memory: const main[-1u]={195};
| eesmith wrote:
| I thought that problem got fixed a few releases ago. Maybe 3.7,
| when some of the peephole optimizer logic was moved to the AST?
|
| At the very least, I can't reproduce it. % cat
| tmp.py (1<<19**8,)*4**7 % python -m compileall tmp.py
| % ls -l __pycache__/tmp.cpython-39.pyc -rw-r--r-- 1
| eesmith admin 167 Feb 16 12:21 __pycache__/tmp.cpython-39.pyc
|
| Python 3.6 generates a 144 byte file. One of the comments says it
| caused a problem in Python 3.3.5.
|
| Another peephole optimizer gotcha that caused problems with older
| Pythons is at https://bugs.python.org/issue30416 :
| def tuple20(): return
| ((((((((1,)*20,)*20,)*20,)*20,)*20,)*20,)*20,)*20
|
| If you have Python 2.7 hanging about, try simply defining that
| function - you can't even ^C it!
| chias wrote:
| I am also unable to reproduce it (Python 3.8.5)
| jwilk wrote:
| I can reproduce it with Python 3.5, but indeed not with 3.6.
| PartiallyTyped wrote:
| I can't reproduce in 2.7.16 and 3.7 either. The tuple20 is an
| interesting one, using lists instead of tuples it doesn't
| explode in size, at least in 2.7
| chrisseaton wrote:
| How is Python able to constant-fold at bytecode compile-time like
| that? I thought operators were redefineable in Python? So could
| they be redefined next time you load the bytecode and the
| constant now invalid? Is that not the case?
| wizzwizz4 wrote:
| They're not redefinable on the built-in types. (Well, they
| _are_ , but not officially.)
___________________________________________________________________
(page generated 2021-02-16 23:00 UTC)