是否有可能在 C 中实现无限编译时间(即没有模板)?
Is it possible to achieve infinite compilation time in C (i.e. without templates)?
所以,标题。众所周知,可以编写 C++ 程序,这将需要无限的时间来编译(理论上)。但是可以用纯 C 编写这样的程序吗?或者有没有办法用一个小程序将编译时间减慢到至少几分钟?
这是您要求的示例,宏呈指数增长。
#define FOO i++ // Substitute any statement here for i++
#define FOO1 FOO ; FOO
#define FOO2 FOO1 ; FOO1
#define FOO3 FOO2 ; FOO2
#define FOO4 FOO3 ; FOO3
#define FOO5 FOO4 ; FOO4
#define FOO6 FOO5 ; FOO5
// Keep going however much you want
...
#define FOO40 FOO39 ; FOO39
volatile int i;
int main(void)
{
FOO40; // This expands to 2^40 statements.
}
我使用 FOO18
进行计时测试,看看会发生什么。我分别测试了预处理器时间和编译时间:
(Preprocessor phase)
time gcc -E foo.c -o foo.i
1.7 seconds
(Compilation phase)
time gcc foo.i -o foo
21 seconds
出于好奇,我一直在尝试越来越大的价值。不幸的是,在某些时候编译器 运行 内存不足(预处理器很好)。我收到此错误:
cc1: out of memory allocating 16842751 bytes after a total of 403505152 bytes
在 FOO16
和 -O2
,我能够在 运行 内存不足的情况下获得 2:23 编译时间。因此,如果您想获得更长的编译时间,请首先找出可以放入单个函数中且不会 运行 内存不足(对我来说 FOO16
)的许多语句。然后做几个函数,像这样:
int main(void)
{
FOO16;
}
void bar1(void)
{
FOO16;
}
void bar2(void)
{
FOO16;
}
// etc...
根据实验,如果您询问最近 GCC or Clang/LLVM to compile with optimizations 一些 C 代码,其中包含一个(或很少的)C 函数和数千条语句,则编译时间会增加很多。
通过经验,使用gcc -O2
单个函数编译需要与语句数 的 平方 成正比的时间(更确切地说,预处理和 gimplification 后 Gimple 语句的数量)。
直觉解释是,寄存器分配、指令调度和中端优化的算法通常比 O(n) 差;天真的非优化 C 编译器,如 tinycc, nwcc、8cc
等没有这样的时间行为(但生成的代码确实比 gcc -O2
...更糟糕)
顺便说一句,你可以玩(在 Linux 上)我的 manydl.c 程序(它生成一些或多或少的随机 C 代码,然后编译它并 dlopen
它,以显示您可以 dlopen
数十万个共享对象)。阅读它的源代码,它会说明我的观点。
更严重的是,我(过去)在旧版本的 MELT 中试验过同样的问题,它生成适合扩展 GCC 的 C++ 代码。我不得不将一些巨大的顺序初始化代码分成几个例程。
您可以使用 gcc -ftime-report -O2
如此庞大的函数进行编译,以便更准确地了解编译器在哪些优化过程中花费了时间。
最后,如果你想要一个小的源代码,你可以通过询问#include "some-huge-file.c"
来作弊,但我认为这不算。
递归包含
#include __FILE__
大多数编译器可能会提前退出,但理论上,这会导致无限编译。
包括(或直接编译,或link反对)设备而不是文件
#include "/dev/tty"
在支持它的系统上,这会导致编译器等待输入。同样,您可以使用命名管道。
找到编译器中的错误
可能编译器有逻辑错误,导致一直循环下去。
所以,标题。众所周知,可以编写 C++ 程序,这将需要无限的时间来编译(理论上)。但是可以用纯 C 编写这样的程序吗?或者有没有办法用一个小程序将编译时间减慢到至少几分钟?
这是您要求的示例,宏呈指数增长。
#define FOO i++ // Substitute any statement here for i++
#define FOO1 FOO ; FOO
#define FOO2 FOO1 ; FOO1
#define FOO3 FOO2 ; FOO2
#define FOO4 FOO3 ; FOO3
#define FOO5 FOO4 ; FOO4
#define FOO6 FOO5 ; FOO5
// Keep going however much you want
...
#define FOO40 FOO39 ; FOO39
volatile int i;
int main(void)
{
FOO40; // This expands to 2^40 statements.
}
我使用 FOO18
进行计时测试,看看会发生什么。我分别测试了预处理器时间和编译时间:
(Preprocessor phase)
time gcc -E foo.c -o foo.i
1.7 seconds
(Compilation phase)
time gcc foo.i -o foo
21 seconds
出于好奇,我一直在尝试越来越大的价值。不幸的是,在某些时候编译器 运行 内存不足(预处理器很好)。我收到此错误:
cc1: out of memory allocating 16842751 bytes after a total of 403505152 bytes
在 FOO16
和 -O2
,我能够在 运行 内存不足的情况下获得 2:23 编译时间。因此,如果您想获得更长的编译时间,请首先找出可以放入单个函数中且不会 运行 内存不足(对我来说 FOO16
)的许多语句。然后做几个函数,像这样:
int main(void)
{
FOO16;
}
void bar1(void)
{
FOO16;
}
void bar2(void)
{
FOO16;
}
// etc...
根据实验,如果您询问最近 GCC or Clang/LLVM to compile with optimizations 一些 C 代码,其中包含一个(或很少的)C 函数和数千条语句,则编译时间会增加很多。
通过经验,使用gcc -O2
单个函数编译需要与语句数 的 平方 成正比的时间(更确切地说,预处理和 gimplification 后 Gimple 语句的数量)。
直觉解释是,寄存器分配、指令调度和中端优化的算法通常比 O(n) 差;天真的非优化 C 编译器,如 tinycc, nwcc、8cc
等没有这样的时间行为(但生成的代码确实比 gcc -O2
...更糟糕)
顺便说一句,你可以玩(在 Linux 上)我的 manydl.c 程序(它生成一些或多或少的随机 C 代码,然后编译它并 dlopen
它,以显示您可以 dlopen
数十万个共享对象)。阅读它的源代码,它会说明我的观点。
更严重的是,我(过去)在旧版本的 MELT 中试验过同样的问题,它生成适合扩展 GCC 的 C++ 代码。我不得不将一些巨大的顺序初始化代码分成几个例程。
您可以使用 gcc -ftime-report -O2
如此庞大的函数进行编译,以便更准确地了解编译器在哪些优化过程中花费了时间。
最后,如果你想要一个小的源代码,你可以通过询问#include "some-huge-file.c"
来作弊,但我认为这不算。
递归包含
#include __FILE__
大多数编译器可能会提前退出,但理论上,这会导致无限编译。
包括(或直接编译,或link反对)设备而不是文件
#include "/dev/tty"
在支持它的系统上,这会导致编译器等待输入。同样,您可以使用命名管道。
找到编译器中的错误
可能编译器有逻辑错误,导致一直循环下去。