Making arbitrarily-large binaries from fixed-size C++ code
C++ programmers know that careless use of templates can bloat your binaries. This got me to thinking, could you write a C++ program that can make an arbitrarily large binary, just by tweaking some constant in the code?
Now of course you could just declare a really large array initialized to some non-zero constant. But that’s too easy. I wanted to see if I can generate an arbitrary amount of code (not data).
My first attempt was simple and straightforward:
The idea here is to keep generating functions f<10000>, f<9999>,
f<9998>
, etc. Each one is a completely separate function that is
emitted into the binary, so each one makes the binary grow a little.
My code here couldn’t technically work since it never terminates the
recursion, but GCC and Clang don’t even let us get that far – they
wisely prevent us from inflicting this bad idea on ourselves:
So our new challenge is: find a way to generate an arbitrary number of functions without exceeding 256 levels of template instantiation depth. Exponential growth to the rescue!
This program will generate roughly 65536 functions, each with its own
unique integer, ie. f<65536>
. It doesn’t exceed an instantiation
depth of 256 because it uses divide and conquer: each level of
instantiation doubles the number of functions, so only lg(N)
levels
of instantiation are required.
On my system, the program above compiles to a 38MB binary. You should be able to make it arbitrarily large, but go too large and you might start running into linker errors!