【发布时间】:2012-11-04 06:51:24
【问题描述】:
以下程序将调用 fun 2 ^ (MAXD + 1) 次。不过,最大递归深度不应该超过 MAXD(如果我的想法是正确的)。因此编译可能需要一些时间,但它不应该吃掉我的 RAM。
#include<iostream>
const int MAXD = 20;
constexpr int fun(int x, int depth=0){
return depth == MAXD ? x : fun(fun(x + 1, depth + 1) + 1, depth + 1);
}
int main(){
constexpr int i = fun(1);
std::cout << i << std::endl;
}
问题在于,吃掉我的内存正是它的作用。当我将 MAXD 提高到 30 时,我的笔记本电脑在 GCC 4.7.2 快速分配 3 GB 左右后开始交换。我还没有尝试使用 clang 3.1,因为我现在无法访问它。
我唯一的猜测是,这与 GCC 试图过于聪明并记住函数调用有关,就像它对模板所做的那样。如果是这样,他们没有限制他们做多少记忆,比如 MRU 缓存表的大小或其他东西,这似乎并不奇怪?我还没有找到禁用它的开关。
我为什么要这样做? 我正在考虑制作一个高级编译时库的想法,比如基因编程之类的。由于编译器没有编译时尾调用优化,我担心任何循环都需要递归并且(即使我调高最大递归深度参数,这看起来有点难看)会快速分配我所有的 RAM 并填充它带有毫无意义的堆栈帧。因此,我想出了上述解决方案,用于在没有深堆栈的情况下获得任意多个函数调用。这样的功能可以用于折叠/循环或蹦床。
编辑: 现在我已经在 clang 3.1 中尝试过了,它根本不会泄漏内存,无论我让它工作多长时间(即我做 MAXD 多高)。 CPU 使用率几乎为 100%,内存使用率几乎为 0%,正如预期的那样。也许这只是 GCC 中的一个错误。
【问题讨论】:
-
我已经确认堆栈永远不会超过 MAXD(如预期的那样),通过运行函数运行时并观察到虽然我可以让它运行很长时间,但它根本不使用 RAM。
-
您是否应该按照gcc.gnu.org/bugs 中的建议报告此问题?
-
@osgx 这并不是一个真正的错误,不是吗?根据标准,我想他们可以对我的 RAM 做他们喜欢做的事。另外,我希望有人知道他们在做什么(你知道你是谁;)告诉我原因是什么。
-
好的,现在我已经在 clang 3.1 上测试过了。 Clang 产生“正确”的行为并且不消耗 RAM。似乎这是 GCC 的错误或功能错误。
-
好的,我已将其报告为错误:gcc.gnu.org/bugzilla/show_bug.cgi?id=55442
标签: c++ gcc c++11 metaprogramming constexpr